Regressione Lineare
La Regressione Lineare (LR) è una tecnica statistica che viene
utilizzata per studiare la relazione tra due o più variabili
quantitative. Il modello di regressione lineare assume che la variabile
dipendente, che si desidera predire, sia una funzione lineare delle
variabili indipendenti.
Il modello di regressione lineare fa le seguenti assunzioni:
- Linearità: La relazione tra la variabile dipendente
e le variabili indipendenti è lineare.
- Normalità: I residui sono distribuiti
normalmente.
- Indipendenza: I residui sono indipendenti tra
loro.
- Eteroschedasticità: La varianza dei residui è
costante.
L’equazione del modello di regressione lineare semplice è la
seguente:
\[ y = a + bx \]
dove:
- y è la variabile dipendente
- a è l’intercetta
- b è il coefficiente angolare
- x è la variabile indipendente
L’intercetta rappresenta il valore medio di y quando x è uguale a 0.
Il coefficiente angolare rappresenta la variazione di y per ogni unità
di variazione di x.
Analisi dei residui
Serve a verificare se il modello soddisfa le assunzioni della
regressione e per identificare eventuali pattern o problemi nei
dati.
Esempio 1:
# Generiamo dati casuali con residui normalmente distribuiti
set.seed(123)
x <- 1:100
y <- 2 * x + rnorm(100)
# Adattiamo un modello di regressione
model <- lm(y ~ x)
# Effettuiamo l'analisi dei residui
Residuals <- residuals(model)
# Creiamo un grafico dei residui
plot(x, Residuals, main = "Distribuzione Normale dei Residui",xlab = "X", ylab = "Residui")
abline(h = 0, col = "red")

In questo caso, i residui seguono una distribuzione normale, il che è
un risultato ideale per un modello di regressione lineare. Quando
diciamo che i residui hanno una distribuzione normale, significa che i
residui seguono una distribuzione a forma di campana, con una media di
zero e una varianza costante. Questa è un’importante assunzione nei
modelli di regressione lineare, in quanto indica che gli errori casuali
nel modello sono distribuiti in modo simmetrico intorno a zero e non
mostrano alcun tipo di tendenza sistemica. Se questa assunzione è
soddisfatta, i test di significatività dei coefficienti del modello e le
stime di intervallo di confidenza saranno affidabili.
Esempio 2:
# Generiamo dati casuali con residui che seguono una distribuzione a U
set.seed(456)
x <- 1:100
y <- 2 * x^2 + rnorm(100)
y[50:60] <- y[50:60] + 10 # Introduciamo un effetto a U nei dati
# Adattiamo un modello di regressione
model <- lm(y ~ x)
# Effettuiamo l'analisi dei residui
residuals <- residuals(model)
# Creiamo un grafico dei residui
plot(x, residuals, main = "Distribuzione a U dei Residui", xlab = "X", ylab = "Residui")
abline(h = 0, col = "red")

In questo caso, i residui mostrano un effetto a U, indicando una
violazione dell’assunzione di omoschedasticità(i residui non mostrano un
aumento o una diminuzione sistematica nella dispersione al variare dei
valori delle variabili indipendenti).
Esempio 3:
# Generiamo dati casuali con outlier nei residui
set.seed(789)
x <- 1:100
y <- 2 * x + rnorm(100)
y[c(20, 85)] <- y[c(20, 85)] + 20 # Aggiungiamo outlier nei dati
# Adattiamo un modello di regressione
model <- lm(y ~ x)
# Effettuiamo l'analisi dei residui
residuals <- residuals(model)
# Creiamo un grafico dei residui
plot(x, residuals, main = "Presenza di Outlier nei Residui", ylab = "Residui", xlab = "X")
abline(h = 0, col = "red")

In questo caso, i residui mostrano la presenza di outlier evidenti,
che possono influenzare in modo significativo la stima dei coefficienti
del modello. Gli outlier possono comportare problemi nei modelli
statistici, specialmente nei modelli di regressione, perché possono
influenzare notevolmente i risultati. Ad esempio, possono influenzare la
stima dei coefficienti del modello e rendere il modello meno
affidabile.
[Torna all’ Indice]
Scomposizione Somma Di Quadrati
La “decomposition of sum of squares” è un concetto fondamentale
nell’analisi della varianza (ANOVA) e nella regressione statistica.
Questa tecnica aiuta a scomporre la varianza totale osservata in un
insieme di dati in diverse componenti, consentendo di comprendere quanto
della varianza può essere attribuito a vari fattori o errori residui. La
formula chiave in questo contesto è:
\[ Varianza Totale = Varianza Spiegata +
Varianza Residua \]
Dove:
Varianza Totale è la varianza complessiva dei dati, cioè quanto i
dati variano in generale.
Varianza Spiegata rappresenta la varianza dovuta al modello o ai
fattori esaminati (spiegati dalla variabile indipendente nel contesto
della regressione).
Varianza Residua è la varianza non spiegata dal modello o dai
fattori ed è associata all’errore residuo, ovvero la differenza tra i
valori osservati e quelli previsti dal modello.
Nel contesto della regressione, puoi rappresentare la decomposizione
della somma dei quadrati come segue:
\[ SST = SSR + SSE \]
SST (Sum of Squares Total) rappresenta la somma dei quadrati
totale ed è la varianza dei dati osservati rispetto alla loro
media.
SSR (Sum of Squares Regression) rappresenta la varianza spiegata
dal modello o dalla variabile indipendente.
SSE (Sum of Squares Error) rappresenta la varianza residua, ossia
la varianza non spiegata dal modello.
Per valutare l’efficienza del tuo modello di regressione, dovresti
guardare la proporzione di questa varianza spiegata dal tuo modello
(SSR). In generale, vuoi massimizzare la proporzione spiegata e
minimizzare la proporzione non spiegata (SSE). Pertanto, punti a
minimizzare SSE.
data <- data.frame(X = c(1, 2, 3, 4, 5), Y = c(3, 5, 6, 8, 10))
mean_Y <- mean(data$Y)
SST <- sum((data$Y - mean_Y)^2)
# Adatta il modello di regressione lineare
model <- lm(Y ~ X, data = data)
# Calcola la SSR
SSR <- sum((predict(model) - mean_Y)^2)
# Calcola la SSE
SSE <- sum(model$residuals^2)
R_squared <- SSR / SST
# Equivale a fare summary(model)
R_squared
[1] 0.989726
[Torna all’ Indice]
Predizione Ottimale
L’“Optimal Prediction” riguarda la determinazione di un modello
predittivo che sia il migliore possibile in termini di accuratezza nel
prevedere gli eventi futuri.
L’obiettivo principale è trovare il modello che massimizza la
precisione delle previsioni, minimizzando l’errore di previsione. Ci
sono vari metodi e tecniche per ottenere la predizione ottimale, a
seconda del contesto e dei dati disponibili.
# Caricamento del dataset "cars"
data(cars)
# Visualizzazione delle prime righe del dataset
head(cars)
# Dividiamo il dataset in set di addestramento e set di test
set.seed(123) # Impostiamo un seed per la riproducibilità
sample_indices <- sample(nrow(cars), nrow(cars) * 0.7) # 70% dati di addestramento
train_data <- cars[sample_indices, ]
test_data <- cars[-sample_indices, ]
# Adattamento di un modello di regressione lineare
model <- lm(dist ~ speed, data = train_data)
# Predizioni
predictions <- predict(model, newdata = test_data)
# Valutazione delle prestazioni
summary(model)
Call:
lm(formula = dist ~ speed, data = train_data)
Residuals:
Min 1Q Median 3Q Max
-18.820 -8.798 -2.272 5.614 44.951
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -22.0481 7.4169 -2.973 0.00548 **
speed 4.0457 0.4589 8.817 3.44e-10 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 13.08 on 33 degrees of freedom
Multiple R-squared: 0.702, Adjusted R-squared: 0.693
F-statistic: 77.73 on 1 and 33 DF, p-value: 3.435e-10
# Grafico dei risultati
library(ggplot2)
ggplot(data = test_data, aes(x = speed, y = dist)) +
geom_point(color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
ggtitle("Predizione della Distanza di Arresto")

[Torna all’ Indice]
Covarianza e Correlazione Empirica
La covarianza e correlazione empirica sono misure statistiche
utilizzate per quantificare la relazione tra due variabili in un insieme
di dati osservati. Queste misure sono strettamente legate e sono spesso
utilizzate per esaminare la relazione lineare tra due variabili.
Covarianza Empirica:
La covarianza empirica è una misura della tendenza di due variabili a
variare insieme. Indica se le due variabili crescono o diminuiscono
simultaneamente (covarianza positiva) o se una aumenta mentre l’altra
diminuisce (covarianza negativa). La formula per calcolare la covarianza
empirica tra due variabili X e Y in un set di dati è data da:
\[ Cov(X,Y) = \frac{1}{n-1} \sum_{i =
1}^n {(X_i - \overline{X})(Y_i - \overline{Y})} \]
Correlazione Empirica:
La correlazione empirica è una versione standardizzata della
covarianza empirica e misura la forza e la direzione di una relazione
lineare tra due variabili. La correlazione empirica è sempre compresa
tra -1 e 1. La formula per calcolare la correlazione empirica tra due
variabili X e Y è data da:
\[ Cor(X,Y) = \frac{Cov(X,Y)}{S_X \cdot
S_Y} \]
Le misure di covarianza empirica e correlazione empirica sono
utilizzate per esaminare la relazione tra variabili in un set di dati e
sono particolarmente utili nell’analisi statistica e nell’apprendimento
automatico per valutare le associazioni tra le variabili prima di
costruire modelli predittivi. La correlazione empirica è più comunemente
utilizzata perché fornisce una misura standardizzata della relazione tra
variabili ed è meno influenzata dall’unità di misura.
Il coefficiente di Pearson è utile per vedere se due variabili hanno
una correlazione lineare o meno. Questo perché non tutte le variabili
correlate hanno una relazione lineare.
Esempio:
# Esempio dati casuali
set.seed(123)
x <- rnorm(100) # Variabile x
y <- 2 * x + rnorm(100) # Variabile y (correlata a x)
# Calcola la correlazione di Pearson
correlation <- cor(x, y)
# Stampa il valore di correlazione
cat("Correlazione di Pearson tra x e y:", correlation, "\n")
Correlazione di Pearson tra x e y: 0.8786993
In questo esempio, stiamo generando dati casuali per le variabili x e
y. La variabile y è costruita come una trasformazione lineare di x con
un termine di errore aggiunto. Poi, utilizziamo la funzione cor() per
calcolare la correlazione di Pearson tra x e y.
Un valore vicino a 1 indica una correlazione lineare positiva forte,
un valore vicino a -1 indica una correlazione lineare negativa forte,
mentre un valore vicino a 0 indica una scarsa correlazione lineare tra
le due variabili.
[Torna all’ Indice]
Regressione Lineare Multipla
La “Multiple Linear Regression” (Regressione Lineare Multipla) è una
tecnica di modellazione statistica utilizzata per analizzare la
relazione tra una variabile dipendente (o target) e due o più variabili
indipendenti (o predittive). Questa tecnica estende la semplice
regressione lineare, che coinvolge solo una variabile indipendente, a un
contesto in cui più variabili indipendenti sono coinvolte nel modello.
La regressione lineare multipla è ampiamente utilizzata nell’analisi
statistica e nell’apprendimento automatico per fare previsioni o
comprendere le relazioni complesse tra variabili.
\[ Y = \beta_0 + \beta_1X_1 + ... +
\beta_nX_n + \epsilon \] L’obiettivo principale è stimare i
coefficienti β in modo che il modello si adatti meglio ai dati
osservati. Questo viene fatto utilizzando metodi di stima, come il
metodo dei minimi quadrati, che cerca di minimizzare la somma dei
quadrati degli errori residui. Il modello di regressione viene valutato
utilizzando metriche di valutazione delle prestazioni come l’errore
quadratico medio (RMSE), il coefficiente di determinazione (R-squared) e
altri. È importante eseguire test di significatività statistica per i
coefficienti delle variabili indipendenti per determinare se esse
contribuiscono significativamente al modello.
La regressione lineare multipla è basata su alcune assunzioni, tra
cui l’indipendenza degli errori, l’omoschedasticità (varianza costante
degli errori), la linearità della relazione e la normalità degli
errori.
# Carica il dataset mtcars
data(mtcars)
# Visualizza le prime righe del dataset
head(mtcars)
# Adattamento del modello di regressione lineare multipla
model <- lm(mpg ~ wt + hp + qsec, data = mtcars)
# Visualizza un riepilogo del modello
summary(model)
Call:
lm(formula = mpg ~ wt + hp + qsec, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-3.8591 -1.6418 -0.4636 1.1940 5.6092
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 27.61053 8.41993 3.279 0.00278 **
wt -4.35880 0.75270 -5.791 3.22e-06 ***
hp -0.01782 0.01498 -1.190 0.24418
qsec 0.51083 0.43922 1.163 0.25463
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.578 on 28 degrees of freedom
Multiple R-squared: 0.8348, Adjusted R-squared: 0.8171
F-statistic: 47.15 on 3 and 28 DF, p-value: 4.506e-11
In sintesi, il modello di regressione lineare multipla suggerisce che
il peso del veicolo influenza il consumo di carburante. La potenza del
motore e il tempo di accelerazione non sono significative per la
spiegazione di questo modello. Nonostante ciò il modello spiega l’83%
dei della variazione nei consumi di carburante.
[Torna all’ Indice]
Approcio Matriciale
L’approccio matriciale alla regressione è una forma alternativa di
rappresentazione e risoluzione dei modelli di regressione, inclusa la
regressione lineare. Questo approccio utilizza notazioni matematiche e
matrici per semplificare i calcoli e ottenere soluzioni più efficienti
in problemi di regressione lineare.
Ci permette di passare da: \[ Y = \beta_0
+ \beta_1X_1 + ... + \beta_nX_n + \epsilon \] a : \[ Y = \beta X + \epsilon \]
La soluzione matriciale per stimare i coefficienti β é: \[ \beta = ((X^T X)^{-1} X^T Y) \]
L’approccio matriciale semplifica la rappresentazione e la
risoluzione dei modelli di regressione, specialmente quando si lavora
con più variabili indipendenti. Inoltre, è utile per comprendere come
eseguire calcoli di regressione in modo più efficiente utilizzando
matrici e algebra lineare, specialmente in contesti di apprendimento
automatico in cui le dimensioni dei dati possono essere elevate.
# Carica il dataset "swiss" (un dataset di dati demografici svizzeri)
data(swiss)
# Visualizza le prime righe del dataset
head(swiss)
# Crea la matrice delle variabili indipendenti
X <- as.matrix(swiss[, c("Examination", "Education")])
# Aggiungi una colonna di 1 per l'intercetta
X <- cbind(1, X)
# Crea il vettore delle variabili dipendenti
Y <- swiss$Fertility
# Calcola i coefficienti del modello utilizzando l'approccio matriciale
beta <- solve(t(X) %*% X) %*% t(X) %*% Y
# Visualizza i coefficienti del modello
print(beta)
[,1]
85.2532753
Examination -0.5572183
Education -0.5394570
# Effettua previsioni con il modello matriciale
predictions <- X %*% beta
# Valuta le prestazioni del modello
model <- lm(Y ~ Examination + Education, data = swiss) # 0 indica di non calcolare l'intercetta
summary(model)
Call:
lm(formula = Y ~ Examination + Education, data = swiss)
Residuals:
Min 1Q Median 3Q Max
-15.9935 -6.8894 -0.3621 7.1640 19.2634
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 85.2533 3.0855 27.630 <2e-16 ***
Examination -0.5572 0.2319 -2.402 0.0206 *
Education -0.5395 0.1924 -2.803 0.0075 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 8.982 on 44 degrees of freedom
Multiple R-squared: 0.5055, Adjusted R-squared: 0.483
F-statistic: 22.49 on 2 and 44 DF, p-value: 1.87e-07
- Esame (Examination): Un aumento nei punteggi di esame è associato a
una diminuzione della fertilità nelle regioni svizzere. Questo
suggerisce che un migliore stato di salute generale, misurato tramite
l’esame, è correlato a una fertilità più bassa.
- Educazione (Education): Un aumento nel livello di educazione è
correlato a una riduzione della fertilità. Le regioni con un livello di
istruzione più elevato tendono ad avere una fertilità più bassa.
[Torna all’ Indice]
Interpretazione Geometrica
L’interpretazione geometrica della regressione lineare è un approccio
concettuale che utilizza uno spazio tridimensionale (o superiore) per
rappresentare visivamente il modello di regressione. In questo spazio,
ogni punto rappresenta un’osservazione nel dataset, e un piano (o
iperpiano) rappresenta il modello di regressione. L’obiettivo è trovare
il piano (o iperpiano) che minimizza la somma dei quadrati delle
distanze verticali tra i punti dati e il piano (o iperpiano). Questo
fornisce una visualizzazione intuitiva di come i coefficienti del
modello vengono stimati per ottenere la migliore “ajustement” ai dati,
minimizzando gli errori residui. L’interpretazione geometrica aiuta a
comprendere i principi fondamentali della regressione lineare e può
essere applicata a problemi più complessi con più variabili
indipendenti.
library(knitr)
library(plotly)
# Genera dati casuali
set.seed(123)
n <- 50
X1 <- rnorm(n)
X2 <- rnorm(n)
Y <- 2 * X1 + 3 * X2 + rnorm(n)
# Crea un dataframe con le variabili
data <- data.frame(X1, X2, Y)
# Adatta il modello di regressione lineare
model <- lm(Y ~ X1 + X2, data = data)
summary(model)
Call:
lm(formula = Y ~ X1 + X2, data = data)
Residuals:
Min 1Q Median 3Q Max
-1.88137 -0.74056 -0.06374 0.52516 2.27045
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.2299 0.1431 -1.607 0.115
X1 2.0252 0.1540 13.150 <2e-16 ***
X2 2.8304 0.1575 17.973 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9975 on 47 degrees of freedom
Multiple R-squared: 0.9107, Adjusted R-squared: 0.9069
F-statistic: 239.8 on 2 and 47 DF, p-value: < 2.2e-16
# Creazione di una griglia di punti
x1_range <- seq(min(X1), max(X1), length = 20)
x2_range <- seq(min(X2), max(X2), length = 20)
grid <- expand.grid(X1 = x1_range, X2 = x2_range)
# Calcolo delle previsioni del modello sulla griglia
grid$Y_pred <- predict(model, newdata = grid)
# Creazione del plot 3D con plotly
plot_ly(data, x = ~X1, y = ~X2, z = ~Y, type = "scatter3d", mode = "markers", marker = list(size = 5, color = "blue")) %>%
add_surface(
x = x1_range,
y = x2_range,
z = matrix(grid$Y_pred, nrow = length(x1_range), ncol = length(x2_range), byrow = TRUE),
colors = "red",
opacity = 0.7
) %>%
layout(scene = list(xaxis = list(title = "X1"), yaxis = list(title = "X2"), zaxis = list(title = "Y")))
NA
L’interpretazione geometrica ci consente di vedere come il piano di
regressione si adatta ai dati nello spazio tridimensionale e come i
coefficienti stimati influenzano la posizione e l’inclinazione del piano
rispetto ai dati osservati. Questo fornisce una visualizzazione
intuitiva della relazione tra le variabili indipendenti e dipendenti nel
contesto della regressione lineare.
[Torna all’ Indice]
Distribuzione F & Anova Table
L’ANOVA valuta globalmente se almeno una delle variabili indipendenti
ha un effetto significativo sulla variabile dipendente, fornisce una
statistica F e il relativo p-value. Un p-value basso suggerisce che
almeno una delle variabili indipendenti è significativa nel modello.
L’ANOVA fornisce quindi una visione complessiva della significatività
del modello nel suo complesso.
L’analisi della varianza (ANOVA) e i “signif. codes” nel summary del
modello forniscono informazioni simili, ma si concentrano su aspetti
diversi dell’analisi.
I “signif. codes” nel summary del modello forniscono una valutazione
variabile per variabile, indicando la significatività statistica di
ciascun coefficiente. Utilizza asterischi (*) o altri simboli per
indicare il livello di significatività, ad esempio, “***” potrebbe
indicare un livello di significatività molto elevato (p-value molto
basso), mentre ” ” (spazio) potrebbe indicare non significativo. Questa
parte del summary fornisce una visione più dettagliata sulla
significatività di ciascuna variabile indipendente separatamente.
L’ANOVA valuta la significatività del modello nel suo insieme, mentre
i “signif. codes” nel summary forniscono una visione dettagliata della
significatività di ciascuna variabile indipendente.
Esempio 1:
# Creiamo un dataset fittizio
set.seed(123)
data <- data.frame(
Gruppo = rep(c("A", "B", "C"), each = 20),
Punteggio = rnorm(60, mean = c(70, 75, 80), sd = 5)
)
# Eseguiamo l'ANOVA
anova_result <- aov(Punteggio ~ Gruppo, data = data)
# Visualizziamo la tabella ANOVA
summary(anova_result)
Df Sum Sq Mean Sq F value Pr(>F)
Gruppo 2 11.3 5.65 0.143 0.867
Residuals 57 2255.9 39.58
In questo esempio, eseguiamo un’ANOVA a un fattore per valutare le
differenze nei punteggi tra i gruppi A, B e C. Il rapporto F e il valore
p ci permettono di determinare se le differenze tra i gruppi sono
statisticamente significative.
I risultati suggeriscono che non ci sono differenze statisticamente
significative tra i gruppi, ossia il variare del gruppo non influenza
significativamente la variabile dipendente. La varianza tra i gruppi è
molto piccola rispetto alla varianza all’interno dei gruppi, e il test F
non è significativo. Questo può indicare che i gruppi sono simili tra
loro per quanto riguarda la variabile in studio.
Esempio 2:
# Creiamo un dataset fittizio
set.seed(123)
data <- data.frame(
Genere = rep(c("Maschio", "Femmina"), each = 50),
Trattamento = rep(c("A", "B"), times = 50),
Punteggio = rnorm(100, mean = c(75, 80), sd = 5)
)
# Eseguiamo l'ANOVA a due fattori
anova_result <- aov(Punteggio ~ Genere * Trattamento, data = data)
# Visualizziamo la tabella ANOVA
summary(anova_result)
Df Sum Sq Mean Sq F value Pr(>F)
Genere 1 7.8 7.8 0.367 0.546
Trattamento 1 575.8 575.8 26.953 1.16e-06 ***
Genere:Trattamento 1 2.6 2.6 0.121 0.729
Residuals 96 2050.8 21.4
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
In questo esempio, eseguiamo un’ANOVA a due fattori per esaminare le
differenze nei punteggi in base al genere e al trattamento.
Dalla tabella dell’ANOVA fornita, possiamo trarre le seguenti
conclusioni:
- Il fattore “Trattamento” ha un forte effetto sulla variabile
dipendente, con un valore di F elevato e un p-value molto basso,
indicando che le differenze tra i trattamenti sono statisticamente
significative (***).
- Il fattore “Genere” non ha un effetto significativo sulla variabile
dipendente, con un valore di F basso e un p-value elevato.
- L’interazione tra “Genere” e “Trattamento” non ha un effetto
significativo sulla variabile dipendente, con un valore di F e un
p-value non significativi.
I risultati dell’ANOVA suggeriscono che il “Trattamento” è il
principale driver delle differenze osservate nella variabile dipendente,
mentre il “Genere” e l’interazione tra “Genere” e “Trattamento” non
sembrano avere un effetto significativo.
- Un valore F maggiore di 1 suggerisce che i parametri o i fattori
sono significativi, poiché la varianza spiegata è maggiore della
varianza non spiegata.
- Un valore F vicino a 1 indica che il modello non spiega in modo
significativo la variabilità nei dati.
- Il valore p associato all’F-value fornisce la probabilità che i
risultati osservati siano dovuti al caso. Un valore p basso (di solito
inferiore a 0.05) indica una significatività elevata, mentre un valore p
alto suggerisce una mancanza di significatività.
Sistema di ipotesi:
Nell’analisi statistica in cui si calcola un valore F, ci sono due
ipotesi principali: l’ipotesi nulla (H0) e l’ipotesi alternativa
(H1).
Ipotesi Nulla (H0): L’ipotesi nulla afferma che non ci sono
differenze significative tra i gruppi o i fattori considerati. In altre
parole, l’ipotesi nulla sostiene che i parametri del modello o i fattori
non hanno un effetto significativo sul risultato o che le differenze
osservate sono casuali.
Ipotesi Alternativa (H1 o HA): L’ipotesi alternativa è il contrario
dell’ipotesi nulla. Sostiene che ci sono differenze significative tra i
gruppi o i fattori considerati, e che le differenze osservate non sono
casuali, ma sono dovute a un effetto significativo dei parametri del
modello o dei fattori.
Continuiamo l’esempio di prima:
model <- lm(Punteggio ~ Genere * Trattamento, data = data)
summary(model)
Call:
lm(formula = Punteggio ~ Genere * Trattamento, data = data)
Residuals:
Min 1Q Median 3Q Max
-12.3383 -3.1482 -0.1363 3.1717 10.9341
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 75.6716 0.9244 81.861 < 2e-16 ***
GenereMaschio -0.2383 1.3073 -0.182 0.855741
TrattamentoB 5.1208 1.3073 3.917 0.000168 ***
GenereMaschio:TrattamentoB -0.6434 1.8488 -0.348 0.728578
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4.622 on 96 degrees of freedom
Multiple R-squared: 0.2223, Adjusted R-squared: 0.198
F-statistic: 9.147 on 3 and 96 DF, p-value: 2.206e-05
# Estraiamo il valore p
p_value <- anova_summary[[1]][["Pr(>F)"]][3] # Usiamo [3] per estrarre il valore relativo all'interazione
# Scegliamo un livello di significatività (alpha)
alpha <- 0.05
# Valutiamo se rifiutare l'ipotesi nulla
if (p_value < alpha) {
cat("Rifiutiamo l'ipotesi nulla. Ci sono differenze significative tra i gruppi.\n")
} else {
cat("Non rifiutiamo l'ipotesi nulla. Non ci sono differenze significative tra i gruppi.\n")
}
Non rifiutiamo l'ipotesi nulla. Non ci sono differenze significative tra i gruppi.
La F-statistic nel summary di un modello lineare (lm) rappresenta la
statistica del test F per l’intero modello. Questo test verifica se c’è
almeno una variabile indipendente nel modello che è significativamente
associata alla variabile dipendente. In altre parole, valuta l’ipotesi
nulla che tutti i coefficienti delle variabili indipendenti nel modello
siano uguali a zero (cioè che non ci siano effetti).
In breve la F-statistic suggerisce che almeno una delle interazioni
tra “Genere” e “Trattamento” o almeno una delle principali effetti è
significativa nel modello.
[Torna all’ Indice]
Modelli Nidificati
Nei modelli statistici, un “nested model” si verifica quando un
modello più complesso o generale può essere suddiviso o semplificato in
un modello più semplice o specifico. Il modello più semplice è
considerato “nidificato” all’interno del modello più complesso, poiché
contiene un sottoinsieme di parametri o vincoli del modello più
generale.
Nel contesto della regressione, i modelli nidificati sono spesso
utilizzati per testare l’aggiunta di variabili indipendenti al modello
al fine di valutare se le variabili aggiuntive migliorano
significativamente la capacità di previsione o spiegazione del modello.
I modelli nidificati sono anche utilizzati in contesti come l’analisi
della varianza (ANOVA), l’analisi della devianza nei modelli lineari
generalizzati (che vedremo più avanti) e altre procedure
statistiche.
Esempio di Modelli di Regressione Nidificati:
Supponiamo di voler creare un modello di regressione per prevedere il
reddito di una persona basandoci su quattro variabili indipendenti: età,
istruzione, esperienza lavorativa e genere. Il modello completo potrebbe
essere:
Modello Completo
\[ Reddito = \beta_0 + \beta_1 \cdot Età +
\beta_2 \cdot Istruzione + \beta_3 \cdot Esperienza + \beta_4 \cdot
Genere \] Tuttavia, potremmo essere interessati a valutare se
l’aggiunta della variabile “genere” migliora significativamente la
capacità predittiva del modello. In tal caso, il modello senza “genere”
è nidificato all’interno del modello completo:
Modello Nidificato
\[ Reddito' = \beta_0 + \beta_1 \cdot
Età + \beta_2 \cdot Istruzione + \beta_3 \cdot Esperienza \]
In questo esempio, il Modello 1 è il modello completo e il Modello 2
è il modello nidificato senza il parametro per “genere”. Valutiamo
tramite un ANOVA quale dei due modelli sia considerato più
significativo.
# Creiamo dati fittizi
set.seed(123)
n <- 100
eta <- rnorm(n, mean = 35, sd = 5)
istruzione <- rnorm(n, mean = 12, sd = 2)
esperienza <- rnorm(n, mean = 10, sd = 3)
genere <- sample(c("Maschio", "Femmina"), n, replace = TRUE)
reddito <- 20 + 2 * eta + 3 * istruzione + 5 * esperienza + ifelse(genere == "Maschio", 4, 0) + rnorm(n, mean = 0, sd = 5)
# Creiamo un dataframe con i dati
data <- data.frame(eta, istruzione, esperienza, genere, reddito)
# Modello completo
modello_completo <- lm(reddito ~ eta + istruzione + esperienza + genere, data = data)
# Modello nidificato senza "genere"
modello_nidificato <- lm(reddito ~ eta + istruzione + esperienza, data = data)
# Test F per confrontare i modelli
anova_result <- anova(modello_nidificato, modello_completo)
# Visualizziamo la tabella ANOVA
print(anova_result)
Analysis of Variance Table
Model 1: reddito ~ eta + istruzione + esperienza
Model 2: reddito ~ eta + istruzione + esperienza + genere
Res.Df RSS Df Sum of Sq F Pr(>F)
1 96 3137.3
2 95 2606.6 1 530.69 19.342 2.852e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Scegliamo un livello di significatività (alpha)
alpha <- 0.05
# Valutiamo se rifiutare l'ipotesi nulla
if (anova_result[2, "Pr(>F)"] < alpha) {
cat("La rimozione di 'genere' non migliora significativamente il modello.\n")
} else {
cat("La rimozione di 'genere' migliora significativamente il modello.\n")
}
La rimozione di 'genere' non migliora significativamente il modello.
# R Squared dei due modelli
print("Modello completo ")
[1] "Modello completo "
summary(modello_completo)$r.squared
[1] 0.9155659
print("Modello annidato ")
[1] "Modello annidato "
summary(modello_nidificato)$r.squared
[1] 0.8983755
[Torna all’ Indice]
Selezione delle variabili
La “variable selection” è un processo attraverso il quale si scelgono
le variabili più rilevanti da includere in un modello statistico. Questo
processo è utile per semplificare i modelli, migliorare la capacità
predittiva e la comprensione dei dati, ridurre l’overfitting e aumentare
l’efficienza computazionale.
Un metodo comune per la selezione delle variabili in R coinvolge
l’utilizzo dell’Information Criterion (Criterio d’Informazione) di
Akaike (AIC) insieme alla funzione step().
AIC (Akaike’s Information Criterion):
Il Criterio d’Informazione di Akaike (AIC) è una metrica che misura
la qualità di un modello statistico. L’obiettivo dell’AIC è trovare il
miglior compromesso tra la bontà di adattamento del modello ai dati e la
sua complessità. L’AIC tiene conto della funzione di verosimiglianza del
modello e penalizza i modelli con un numero maggiore di parametri. L’AIC
è definito come:
\[ AIC = -2logLikelihood + 2k
\]
Dove:
- “log-likelihood” è il logaritmo della funzione di verosimiglianza
del modello.
- “k” è il numero di parametri stimati nel modello. Un valore AIC più
basso indica un modello migliore, in quanto indica un migliore
adattamento ai dati con meno complessità.
Funzione step():
La funzione step() in R è utilizzata per effettuare la selezione
delle variabili basata su criteri come l’AIC. Consente di confrontare e
selezionare i modelli in modo automatico aggiungendo o rimuovendo
variabili dal modello, fino a trovare il modello con l’AIC più basso. La
sintassi di base della funzione step() è la seguente:
#step(modello_iniziale, direction = "both", scope = list(lower = modello_minimo, upper = modello_massimo))
- modello_iniziale è il modello di partenza che desideri semplificare
o migliorare.
- direction può essere “forward”, “backward”, o “both” e specifica se
aggiungere, rimuovere o entrambi i tipi di variabili durante la
selezione.
- scope specifica l’intervallo dei modelli da considerare durante la
selezione. Il - “modello_minimo” rappresenta il modello più semplice
possibile (ad esempio, un modello con solo l’intercetta), mentre il
“modello_massimo” rappresenta il modello più complesso (il modello
completo con tutte le variabili).
# Carica il dataset di esempio
data(mtcars)
# Crea un modello lineare iniziale
all <- lm(mpg ~ ., data = mtcars)
# Esegui la selezione delle variabili basata su AIC
best <- step(all, direction = "backward")
Start: AIC=70.9
mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb
Df Sum of Sq RSS AIC
- cyl 1 0.0799 147.57 68.915
- vs 1 0.1601 147.66 68.932
- carb 1 0.4067 147.90 68.986
- gear 1 1.3531 148.85 69.190
- drat 1 1.6270 149.12 69.249
- disp 1 3.9167 151.41 69.736
- hp 1 6.8399 154.33 70.348
- qsec 1 8.8641 156.36 70.765
<none> 147.49 70.898
- am 1 10.5467 158.04 71.108
- wt 1 27.0144 174.51 74.280
Step: AIC=68.92
mpg ~ disp + hp + drat + wt + qsec + vs + am + gear + carb
Df Sum of Sq RSS AIC
- vs 1 0.2685 147.84 66.973
- carb 1 0.5201 148.09 67.028
- gear 1 1.8211 149.40 67.308
- drat 1 1.9826 149.56 67.342
- disp 1 3.9009 151.47 67.750
- hp 1 7.3632 154.94 68.473
<none> 147.57 68.915
- qsec 1 10.0933 157.67 69.032
- am 1 11.8359 159.41 69.384
- wt 1 27.0280 174.60 72.297
Step: AIC=66.97
mpg ~ disp + hp + drat + wt + qsec + am + gear + carb
Df Sum of Sq RSS AIC
- carb 1 0.6855 148.53 65.121
- gear 1 2.1437 149.99 65.434
- drat 1 2.2139 150.06 65.449
- disp 1 3.6467 151.49 65.753
- hp 1 7.1060 154.95 66.475
<none> 147.84 66.973
- am 1 11.5694 159.41 67.384
- qsec 1 15.6830 163.53 68.200
- wt 1 27.3799 175.22 70.410
Step: AIC=65.12
mpg ~ disp + hp + drat + wt + qsec + am + gear
Df Sum of Sq RSS AIC
- gear 1 1.565 150.09 63.457
- drat 1 1.932 150.46 63.535
<none> 148.53 65.121
- disp 1 10.110 158.64 65.229
- am 1 12.323 160.85 65.672
- hp 1 14.826 163.35 66.166
- qsec 1 26.408 174.94 68.358
- wt 1 69.127 217.66 75.350
Step: AIC=63.46
mpg ~ disp + hp + drat + wt + qsec + am
Df Sum of Sq RSS AIC
- drat 1 3.345 153.44 62.162
- disp 1 8.545 158.64 63.229
<none> 150.09 63.457
- hp 1 13.285 163.38 64.171
- am 1 20.036 170.13 65.466
- qsec 1 25.574 175.67 66.491
- wt 1 67.572 217.66 73.351
Step: AIC=62.16
mpg ~ disp + hp + wt + qsec + am
Df Sum of Sq RSS AIC
- disp 1 6.629 160.07 61.515
<none> 153.44 62.162
- hp 1 12.572 166.01 62.682
- qsec 1 26.470 179.91 65.255
- am 1 32.198 185.63 66.258
- wt 1 69.043 222.48 72.051
Step: AIC=61.52
mpg ~ hp + wt + qsec + am
Df Sum of Sq RSS AIC
- hp 1 9.219 169.29 61.307
<none> 160.07 61.515
- qsec 1 20.225 180.29 63.323
- am 1 25.993 186.06 64.331
- wt 1 78.494 238.56 72.284
Step: AIC=61.31
mpg ~ wt + qsec + am
Df Sum of Sq RSS AIC
<none> 169.29 61.307
- am 1 26.178 195.46 63.908
- qsec 1 109.034 278.32 75.217
- wt 1 183.347 352.63 82.790
In questo esempio, partiamo da un modello lineare completo che
utilizza tutte le variabili di mtcars, e poi utilizziamo step() per
eseguire la selezione delle variabili basata su AIC. Alla fine,
otteniamo il modello con l’AIC più basso, che dovrebbe essere una
versione semplificata del modello iniziale con solo le variabili più
rilevanti.
La “variable selection” utilizzando AIC e step() è un potente
strumento per migliorare la qualità e l’interpretabilità dei modelli
statistici, in particolare quando si hanno molti potenziali
predittori.
[Torna all’ Indice]
Predizioni Categoriche
Nell’analisi statistica, i “categorical predictors” sono variabili
che rappresentano categorie o gruppi distinti anziché valori numerici.
Queste variabili sono anche conosciute come variabili qualitative o
fattori. Ad esempio, il genere (maschio/femmina), il livello di
istruzione (scuola elementare, scuola media, laurea), o il tipo di
prodotto (A, B, C) sono esempi di predittori categorici. Quando si
utilizzano predittori categorici in un modello statistico, è importante
considerare come gestire e interpretare questi dati.
Una considerazione fondamentale è come rappresentare le variabili
categoriche nel modello. Solitamente, vengono utilizzate delle variabili
dummy (variabili indicatrici) per rappresentare le categorie. Ad
esempio, nel caso del genere (maschio/femmina), potrebbero essere create
due variabili dummy, una per il maschio e una per la femmina. Queste
variabili dummy prendono il valore 1 o 0 a seconda dell’appartenenza
alla categoria. Questo approccio consente al modello di catturare
l’effetto della categoria sulla variabile dipendente.
Oltre alla rappresentazione delle variabili categoriche, è importante
considerare le interazioni tra i predittori. Le interazioni si
verificano quando l’effetto di una variabile categorica sul risultato
dipende da un’altra variabile. Ad esempio, l’effetto del livello di
istruzione sul reddito potrebbe variare in base al genere. In questo
caso, c’è un’interazione tra il livello di istruzione e il genere.
Per esaminare le interazioni tra predittori categorici, è possibile
utilizzare l’analisi della varianza (ANOVA) o i modelli lineari
generalizzati (che vedremo più avanti). Le interazioni possono fornire
informazioni preziose sull’influenza combinata delle variabili
categoriche sul risultato.
# Creiamo dati fittizi
set.seed(123)
n <- 100
genere <- sample(c("Maschio", "Femmina"), n, replace = TRUE)
istruzione <- rep(c("Elementare", "Media", "Laurea"), length.out = n )
reddito <- 30 + ifelse(genere == "Maschio", 5, 0) + ifelse(istruzione == "Laurea", 10, 0) + rnorm(n, mean = 0, sd = 5)
# Creiamo un dataframe con i dati
data <- data.frame(genere, istruzione, reddito)
# Modello con interazione tra genere e istruzione
modello <- lm(reddito ~ genere * istruzione, data = data)
# Visualizziamo i risultati
summary(modello)
Call:
lm(formula = reddito ~ genere * istruzione, data = data)
Residuals:
Min 1Q Median 3Q Max
-9.3888 -3.0121 -0.6269 2.6272 11.0710
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 27.8429 1.2794 21.763 < 2e-16 ***
genereMaschio 5.8726 1.6681 3.521 0.000666 ***
istruzioneLaurea 12.0839 1.8438 6.554 2.98e-09 ***
istruzioneMedia 3.3778 1.7519 1.928 0.056860 .
genereMaschio:istruzioneLaurea -1.3699 2.3856 -0.574 0.567186
genereMaschio:istruzioneMedia -0.8084 2.3586 -0.343 0.732535
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4.787 on 94 degrees of freedom
Multiple R-squared: 0.5839, Adjusted R-squared: 0.5618
F-statistic: 26.38 on 5 and 94 DF, p-value: < 2.2e-16
anova(modello, test = "chi")
Analysis of Variance Table
Response: reddito
Df Sum Sq Mean Sq F value Pr(>F)
genere 1 738.22 738.22 32.2149 1.525e-07 ***
istruzione 2 2277.06 1138.53 49.6837 1.892e-15 ***
genere:istruzione 2 7.66 3.83 0.1672 0.8463
Residuals 94 2154.06 22.92
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Grafico reddito per soli maschi e sole femmine
ggplot(data = data, aes(x = istruzione, y = reddito, fill = genere)) +
geom_boxplot() +
labs(x = "Istruzione", y = "Reddito")

In questo esempio, stiamo creando dati fittizi con due predittori
categorici: “genere” e “istruzione”. Il modello lineare include
un’interazione tra questi due predittori. La tabella dei risultati
summary(modello) mostra come i predittori categorici e l’interazione
influenzano il reddito.
Possiamo concludere che il genere e il livello di istruzione hanno un
effetto significativo sul reddito, mentre le interazioni tra genere e
istruzione non sono significative in questo modello. Il modello nel suo
complesso è significativo e in grado di spiegare una parte della
variazione nel reddito.
Fattori con più di due categorie:
Quando si affrontano fattori con più di due livelli (categorie), è
necessario considerare come gestire queste variabili nel modello. In
generale, un fattore con k livelli richiede la creazione di k-1
variabili dummy per evitare la “dummy variable trap”. Questo si verifica
quando le variabili dummy sono linearmente dipendenti e possono portare
a problemi di multicollinearità.
Ad esempio, se abbiamo una variabile “colore” con tre livelli (rosso,
verde, blu), dovremmo creare due variabili dummy per rappresentarla. Una
rappresenterà il rosso e l’altra il verde. Se entrambe le variabili
dummy sono uguali a 0, ciò significa che il colore è blu. Questo evita
la trap della variabile dummy.
# Creiamo dati fittizi
set.seed(123)
n <- 100
colore <- rep(c("Rosso", "Verde", "Blu"), length.out = n )
voto <- rnorm(n, mean = 50, sd = 10)
# Creiamo un dataframe con i dati
data <- data.frame(colore, voto)
# Modello con un fattore con più di due livelli
modello <- lm(voto ~ colore, data = data)
# Visualizziamo i risultati
summary(modello)
Call:
lm(formula = voto ~ colore, data = data)
Residuals:
Min 1Q Median 3Q Max
-23.6349 -6.1247 -0.4198 5.7870 21.9547
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 50.5432 1.5932 31.725 <2e-16 ***
coloreRosso 1.8459 2.2364 0.825 0.411
coloreVerde -0.8084 2.2531 -0.359 0.721
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 9.152 on 97 degrees of freedom
Multiple R-squared: 0.01508, Adjusted R-squared: -0.005228
F-statistic: 0.7426 on 2 and 97 DF, p-value: 0.4786
I risultati indicano che il colore del prodotto (rosso o verde) non
ha un impatto significativo sul voto. L’intercetta, che rappresenta il
colore “Blu,” è significativa, ma il modello nel suo insieme non è molto
efficace nel spiegare la variazione nei voti.
[Torna all’ Indice]
Controllo del Modello
Il Model Checking è una fase cruciale nell’analisi statistica,
specialmente quando si adotta un modello di regressione. Durante questa
fase, si valuta se il modello soddisfa le principali assunzioni dei
modelli lineari. Le quattro assunzioni principali da verificare
sono:
- Linearity (Linearità): Questa assunzione afferma
che la risposta (variabile dipendente) può essere scritta come una
combinazione lineare delle variabili predittive (variabili
indipendenti). In altre parole, il modello dovrebbe essere in grado di
catturare il rapporto tra le variabili in modo lineare, con un certo
grado di rumore residuo. La linearità può essere verificata attraverso
grafici di dispersione o grafici residui.
- Independence (Indipendenza): Questa assunzione
richiede che gli errori (residui) del modello siano indipendenti l’uno
dall’altro. Ciò significa che il valore di errore per un’osservazione
non è influenzato dal valore di errore per un’altra osservazione.
L’indipendenza può essere verificata osservando i grafici dei residui in
sequenza temporale o spaziale, a seconda del contesto.
- Normality (Normalità): L’assunzione di normalità
richiede che i residui del modello seguano una distribuzione normale.
Questo è importante perché molte procedure statistiche si basano
sull’ipotesi di normalità dei residui. La normalità può essere
verificata tramite grafici quantile-quantile (QQ plot) o istogrammi dei
residui.
- Equal Variance (Varianza Uniforme): Questa
assunzione, chiamata anche omoschedasticità, richiede che la varianza
dei residui sia costante in tutti i livelli delle variabili predittive.
In altre parole, non dovrebbe esserci alcun modello discernibile nella
varianza dei residui. La varianza uniforme può essere verificata
osservando i grafici dei residui rispetto ai valori predetti.
Per verificare queste assunzioni, i Residuals-based displays (grafici
basati sui residui) sono spesso utilizzati. Questi includono:
- Scatterplot dei residui: Un grafico dei residui contro i valori
previsti o le variabili predittive. Questo può rivelare se c’è una
struttura non lineare nei residui.
- Grafico di sequenza temporale dei residui: Utilizzato quando i dati
sono raccolti nel tempo, questo grafico può rivelare dipendenze
temporali nei residui.
- QQ-plot (Quantile-Quantile plot): Questo grafico confronta i
quantili dei residui con quelli di una distribuzione normale. Se i punti
del grafico seguono una linea retta, i residui sono approssimativamente
normali.
- Istogramma dei residui: Un istogramma dei residui può dare un’idea
della loro distribuzione e normalità.
Rispettare queste assunzioni è importante per garantire che le stime
del modello siano affidabili e che le conclusioni siano valide. Se una o
più di queste assunzioni non sono soddisfatte, potrebbero essere
necessarie correzioni al modello o ai dati stessi.
[Torna all’ Indice]
Transformazioni
Le trasformazioni sono una tecnica utilizzata nella modellazione
statistica per modificare le relazioni tra variabili al fine di
soddisfare meglio le assunzioni del modello. Le trasformazioni possono
essere utili quando le relazioni tra le variabili non sono lineari o
quando le assunzioni di omoschedasticità o normalità dei residui non
sono soddisfatte. Di seguito, affrontiamo i seguenti argomenti relativi
alle trasformazioni:
Variance Stabilizing Transformations (Trasformazioni per
Stabilizzare la Varianza): In alcuni casi, la varianza dei dati può
variare in modo non costante con il cambiare del valore medio. Questo
fenomeno è noto come eteroschedasticità. Le trasformazioni possono
essere utilizzate per stabilizzare la varianza, rendendo la relazione
tra il valore medio e la varianza più costante. Un esempio comune è la
trasformazione di Box-Cox.
Box-Cox Transform: La trasformazione di Box-Cox è una tecnica
utilizzata per stabilizzare la varianza e rendere i dati
approssimativamente normali. È definita come:
\[
y(\lambda) = \begin{cases} \frac{(y^\lambda - 1)}{\lambda} &
\text{se } \lambda \neq 0 \\
\log(y) & \text{se } \lambda = 0
\end{cases}
\]
Dove y sono i dati originali e λ è il parametro di trasformazione. È
possibile calcolare il valore ottimale di λ che massimizza la normalità
dei dati.
library(ggplot2)
library(MASS)
library(gridExtra)
# Genera dati casuali
set.seed(123)
data <- data.frame(y = rgamma(100, shape = 2, scale = 1))
# Applica la trasformazione di Box-Cox
result <- boxcox(y ~ 1, data = data)

lambda <- result$x[which.max(result$y)]
transformed_data <- if (lambda == 0) log(data$y) else ((data$y^lambda - 1) / lambda)
# Visualizza il valore ottimale di lambda
cat("Valore ottimale di lambda: ", lambda, "\n")
Valore ottimale di lambda: 0.3838384
# Crea un dataframe con i dati originali e trasformati
plot_data <- data.frame(Original = data$y, Transformed = transformed_data)
# Plotta i dati originali
plot_original <- ggplot(plot_data, aes(x = Original)) +
geom_histogram(binwidth = 0.5, fill = "blue", alpha = 0.7) +
labs(title = "Distribuzione dei dati originali")
# Plotta i dati trasformati
plot_transformed <- ggplot(plot_data, aes(x = Transformed)) +
geom_histogram(binwidth = 0.1, fill = "green", alpha = 0.7) +
labs(title = "Distribuzione dei dati trasformati")
# Mostra i grafici sulla stessa riga
grid.arrange(plot_original, plot_transformed, ncol = 2)

- Polynomials (Polinomi): Le trasformazioni polinomiali consentono di
modellare relazioni non lineari tra variabili. È possibile aggiungere
termini polinomiali al modello di regressione per catturare curve o
relazioni più complesse. Ad esempio, si possono utilizzare polinomi di
secondo grado per modellare una relazione quadratica tra una variabile
indipendente e la variabile dipendente. L’aggiunta di termini
polinomiali può migliorare l’adattamento del modello ai dati, ma è
importante evitare di aggiungere troppi termini polinomiali per evitare
l’overfitting.
# Modello lineare con un termine polinomiale di secondo grado
model <- lm(y ~ x + I(x^2), data = data)
- Transformations of Predictor Variables (Trasformazioni delle
Variabili Predittive): Le trasformazioni delle variabili predittive sono
utilizzate per adattare i dati in modo che soddisfino meglio le
assunzioni del modello. Queste trasformazioni coinvolgono la modifica
delle variabili indipendenti piuttosto che della variabile dipendente.
Possono essere utilizzate per rendere le relazioni tra le variabili più
lineari o per stabilizzare la varianza. Ad esempio, è possibile
applicare una trasformazione logaritmica o una radice quadrata a una
variabile predittiva per renderla più lineare nei confronti della
variabile dipendente.
# Creiamo dati fittizi
set.seed(123)
X <- rnorm(100, mean = 10, sd = 2)
Y <- 2 * X + rnorm(100, mean = 0, sd = 1)
# Creiamo un dataframe con i dati
data <- data.frame(X, Y)
# Modello lineare senza trasformazione
model_no_transform <- lm(Y ~ X, data = data)
# Visualizziamo il summary del modello senza trasformazione
summary(model_no_transform)
Call:
lm(formula = Y ~ X, data = data)
Residuals:
Min 1Q Median 3Q Max
-1.9073 -0.6835 -0.0875 0.5806 3.2904
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.15956 0.55265 0.289 0.773
X 1.97376 0.05344 36.935 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9707 on 98 degrees of freedom
Multiple R-squared: 0.933, Adjusted R-squared: 0.9323
F-statistic: 1364 on 1 and 98 DF, p-value: < 2.2e-16
# Trasformiamo la variabile X applicando il logaritmo
data$X_transformed <- log(data$X)
# Modello lineare con la variabile X trasformata
model_with_transform <- lm(Y ~ X_transformed, data = data)
# Visualizziamo il summary del modello con la variabile X trasformata
summary(model_with_transform)
Call:
lm(formula = Y ~ X_transformed, data = data)
Residuals:
Min 1Q Median 3Q Max
-1.9290 -0.7441 -0.1202 0.5388 3.3305
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -24.1696 1.2961 -18.65 <2e-16 ***
X_transformed 19.2819 0.5608 34.38 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.037 on 98 degrees of freedom
Multiple R-squared: 0.9235, Adjusted R-squared: 0.9227
F-statistic: 1182 on 1 and 98 DF, p-value: < 2.2e-16
Le trasformazioni sono strumenti potenti per adattare i modelli ai
dati in modo più accurato quando le relazioni tra variabili non sono
lineari o quando le assunzioni del modello non sono soddisfatte.
Tuttavia, è importante scegliere con attenzione le trasformazioni per
evitare il sovradattamento e garantire che i risultati siano
interpretabili.
[Torna all’ Indice]
Multicollinearità
La multicollinearità si verifica quando due o più variabili
indipendenti in un modello di regressione sono fortemente correlate tra
loro. Questa correlazione tra le variabili indipendenti può rendere
difficile l’interpretazione del modello e portare a stime poco
affidabili dei coefficienti di regressione. La presenza di
multicollinearità può causare un aumento del Variance Inflation Factor
(VIF), una misura comune utilizzata per valutare la multicollinearità
tra le variabili indipendenti in un modello di regressione. Un alto VIF
per una variabile indica che quella variabile è fortemente correlata con
le altre variabili indipendenti nel modello.
Variance Inflation Factor:
Il VIF di ciascuna variabile indipendente è calcolato come il
rapporto della varianza dell’errore standard del coefficiente di
regressione stimato per quella variabile rispetto alla varianza
dell’errore standard se la variabile fosse stata completamente non
correlata alle altre variabili indipendenti. In generale, un VIF
superiore a 5 o 10 è spesso considerato un segno di multicollinearità
significativa.
\[
VIF_i = (X^TX)_{i+1,i+1}^{-1}*ns^2_{X_i} \ \ oppure \ \ VIF_i =
\frac{1}{1-R^2_i}
\]
# Load the necessary library
library(car)
# Create a sample dataset with multiple predictor variables
set.seed(123)
data <- data.frame(
X1 = rnorm(100),
X2 = rnorm(100),
X3 = rnorm(100),
X4 = rnorm(100)
)
# Add a dependent variable (response)
data$Y <- 2 * data$X1 + 3 * data$X2 + 1.5 * data$X3 + rnorm(100)
# Fit a linear regression model
model <- lm(Y ~ X1 + X2 + X3 + X4, data = data)
# Calculate VIF
vif_values <- vif(model)
# Print the VIF values
vif_values
X1 X2 X3 X4
1.021515 1.004920 1.020348 1.006429
Tutti i valori VIF sono vicini a 1, il che suggerisce che non c’è una
forte multicollinearità tra le variabili predittive X1, X2, X3 e X4.
Questo è un buon segno, poiché significa che le variabili non sono
fortemente correlate tra loro.
Valori VIF più elevati indicano una multicollinearità più forte, e
valori al di sopra di una certa soglia (ad esempio, VIF > 5) possono
suggerire la necessità di affrontare la collinearità, ad esempio,
rimuovendo una delle variabili predittive correlate.
[Torna all’ Indice]
Punti Influenti
I punti influenti si riferiscono a osservazioni nei dati che hanno un
impatto significativo sui risultati di un’analisi statistica, come una
regressione lineare. Questi punti possono influenzare la stima dei
parametri del modello, i residui, i valori p, l’R-squared e altre
statistiche di rilevanza. Ci sono diverse metriche utilizzate per
identificare i punti influenti, tra cui Standardized Residuals,
Studentized Residuals e Cook’s Distance.
- Standardized Residuals (Residui Standardizzati): Questi sono i
residui divisi per la deviazione standard dei residui. Un residuo
standardizzato è una misura di quanto un punto dato si discosti dalla
linea di regressione in termini di deviazioni standard. I punti con
residui standardizzati molto grandi (positivi o negativi) sono
considerati influenti.
- Studentized Residuals (Residui Studentizzati): Questi sono i residui
divisi per una stima della deviazione standard dell’errore residuo. I
residui studentizzati sono utilizzati per valutare quanto un punto dato
sia influente considerando l’effetto delle altre osservazioni nel
dataset. I punti con residui studentizzati significativamente grandi in
valore assoluto sono considerati influenti.
- Cook’s Distance (Distanza di Cook): Cook’s Distance è una metrica
che combina l’effetto di un punto sui parametri del modello e il suo
effetto sui residui. I punti con Cook’s Distance molto grandi sono
considerati influenti. Cook’s Distance è spesso utilizzato per
identificare punti che, se rimossi, avrebbero un impatto significativo
sui risultati del modello.
Nel contesto della regressione, i punti influenti possono derivare da
outlier nei dati, dati errati o punti che influenzano notevolmente la
stima dei parametri. Identificare e trattare i punti influenti è
importante per garantire che il modello di regressione sia affidabile e
rappresenti accuratamente i dati. La rimozione di punti influenti può
migliorare la bontà di adattamento del modello e l’accuratezza delle
previsioni.
# Carichiamo il dataset di esempio
data(mtcars)
# Adattiamo un modello di regressione lineare
model <- lm(mpg ~ wt + hp, data = mtcars)
# Calcoliamo i residui standardizzati
standardized_residuals <- rstandard(model)
# Identifichiamo i punti influenti basati sui residui standardizzati
influential_points <- which(abs(standardized_residuals) > 2)
# Visualizziamo gli indici dei punti influenti
cat("Punti influenti basati sui residui standardizzati:", influential_points, "\n")
Punti influenti basati sui residui standardizzati: 17 18 20
# Calcoliamo Cook's Distance
cook_distance <- cooks.distance(model)
# Identifichiamo i punti influenti basati su Cook's Distance
influential_points_cook <- which(cook_distance > 4 / length(cook_distance))
# Visualizziamo gli indici dei punti influenti basati su Cook's Distance
cat("Punti influenti basati su Cook's Distance:", influential_points_cook, "\n")
Punti influenti basati su Cook's Distance: 17 18 20 31
par(mfrow = c(1,2))
# Grafico dei punti con evidenziazione dei punti influenti
plot(mtcars$wt, mtcars$mpg, pch = 16, main = "Punti Influenti (Stan e Stud)",
xlab = "Peso (wt)", ylab = "Miglia per gallone (mpg)")
points(mtcars$wt[influential_points], mtcars$mpg[influential_points], pch = 16, col = "red", cex = 1.5)
plot(mtcars$wt, mtcars$mpg, pch = 16, main = "Punti Influenti (Cook)",
xlab = "Peso (wt)", ylab = "Miglia per gallone (mpg)")
points(mtcars$wt[influential_points_cook], mtcars$mpg[influential_points_cook], pch = 16, col = "red", cex = 1.5)

Leverage:
Il “Leverage” è una misura utilizzata nell’analisi dei dati
statistici per identificare punti influenti o osservazioni atipiche in
un modello di regressione. Questa misura valuta quanto un’osservazione
può influenzare i risultati del modello, in particolare i coefficienti
di regressione. Il leverage è calcolato sulla base delle variabili
predittive e può essere utilizzato per identificare le osservazioni che
hanno un impatto significativo sul modello.
Identificazione dei punti influenti: I punti con un valore di
leverage significativamente più alto degli altri sono quelli che possono
influenzare notevolmente il modello. Puoi stabilire una soglia
arbitraria o utilizzare metodi statistici per determinare quali punti
sono influenti. Ad esempio, i punti con leverage superiore a 2 volte la
media possono essere considerati influenti.
Esame dei punti influenti: Una volta identificati i punti influenti,
è possibile esaminarli ulteriormente per determinare se sono
effettivamente outliers o errori di misurazione. Potresti voler
esaminare le osservazioni con elevate differenze tra i valori osservati
e quelli previsti dal modello.
È importante notare che la rimozione dei punti influenti dovrebbe
essere effettuata con cautela e solo se c’è una giustificazione valida.
In alcuni casi, potresti scegliere di mantenere i punti influenti nel
modello se ritieni che rappresentino informazioni significative o se
hanno una spiegazione plausibile.
# Generiamo dati casuali
set.seed(123)
n <- 100
x <- rnorm(n)
y <- 2 * x + rnorm(n)
# Adattiamo un modello di regressione lineare
model <- lm(y ~ x)
# Calcoliamo i valori di leverage
leverage <- hatvalues(model)
# Identifichiamo i punti influenti
infl_points <- which(leverage > 2 * mean(leverage))
# Visualizziamo i punti influenti
print(infl_points)
6 16 18 26 44 57 70 72 97
6 16 18 26 44 57 70 72 97
par(mfrow = c(1,2))
# Plot del grafico
plot(x, y)
points(x[infl_points], y[infl_points], col = "blue", pch = 19)
# Plot del Leverage
plot(x, leverage)
points(x[infl_points], leverage[infl_points], col = "blue", pch = 19)

Nota che nell’esempio abbiamo utilizzato una soglia di leverage
arbitraria (2 volte la media) per identificare i punti influenti. In
un’applicazione pratica, è consigliabile considerare la soglia in base
al contesto del problema e all’analisi dei dati.
[Torna all’ Indice]
Modelli Lineari Generalizzati
I GLM estendono il framework della regressione lineare per gestire
un’ampia gamma di distribuzioni dei dati e tipologie di risposte. A
differenza della regressione lineare tradizionale, i GLM possono
accomodare distribuzioni di errori non normali e modellare relazioni tra
predittori e risposte attraverso una funzione di collegamento.
Un GLM è caratterizzato da tre componenti principali:
Componente Casuale (Distribuzione): La variabile
di risposta \(Y\) segue una
distribuzione di probabilità dalla famiglia esponenziale, che include
distribuzioni comuni come normale, binomiale e di Poisson.
Componente Sistematica (Predittore Lineare): La
relazione tra i predittori e il valore atteso della risposta è espressa
attraverso un predittore lineare (\(\eta\)). Il predittore lineare è una
combinazione dei predittori, ognuno moltiplicato per un parametro, e si
collega alla media della risposta attraverso una funzione di
collegamento.
Funzione di Collegamento: La funzione di
collegamento (\(g(\mu)\)) stabilisce il
collegamento tra il predittore lineare e la media della risposta.
Trasforma la scala della variabile di risposta e assicura che il
predittore lineare copra l’intera linea reale. Le funzioni di
collegamento comuni includono logit, probit e identità.
La forma generale di un GLM può essere rappresentata come segue:
\[ g(\mu) = X\beta \]
Dove:
- \(g(\mu)\) è la funzione di
collegamento.
- \(\mu\) è il valore atteso della
variabile di risposta.
- \(X\) è la matrice dei
predittori.
- \(\beta\) è il vettore dei
coefficienti.
Esempi:
Regressione Logistica Binaria:
- Distribuzione: Binomiale
- Funzione di Collegamento: Logit (log-rapporti di
probabilità)
- Equazione: \(\text{logit}(\mu) = X\beta\)
Descrizione: La funzione di collegamento logit
trasforma la probabilità di successo (\(\mu\)) in un predittore lineare. In questo
caso, il modello logistic descrive come la log-odds della probabilità di
successo sia lineare rispetto ai predittori.
Regressione di Poisson:
- Distribuzione: Poisson
- Funzione di Collegamento: Log
- Equazione: \(\log(\mu) =
X\beta\)
Descrizione: Con la funzione di collegamento
logaritmico, il modello di Poisson può gestire dati di conteggio, poiché
connette il logaritmo naturale del valore atteso (\(\mu\)) a un predittore lineare.
Regressione Gamma:
- Distribuzione: Gamma
- Funzione di Collegamento: Inverso
- Equazione: \(\frac{1}{\mu} = X\beta\)
Descrizione: La funzione di collegamento inversa in
un modello gamma è appropriata quando si modellano variabili con
distribuzioni a coda pesante. Collega l’inverso del valore atteso (\(\mu\)) a un predittore lineare.
Devianza
La devianza è una misura della discrepanza tra il modello statistico
e i dati osservati nei GLM. In generale, la devianza è utilizzata per
confrontare modelli alternativi e valutare quanto bene un modello si
adatta ai dati. Nel contesto dei GLM, la devianza è particolarmente
significativa perché tiene conto delle specifiche distribuzioni delle
variabili di risposta.
La devianza si calcola confrontando il modello fitted (previsto) con
un modello null, spesso noto come modello null di saturazione. Il
modello null rappresenta l’ipotesi che tutti i parametri del modello
siano uguali a zero, indicando l’assenza di effetti predittori. La
devianza è data dalla seguente formula:
\[ D = 2 \times \left( \ell(\hat{\beta}) -
\ell(\beta_0) \right) \]
Dove:
- \(\ell(\hat{\beta})\) è il
log-likelihood del modello fitted.
- \(\ell(\beta_0)\) è il
log-likelihood del modello null.
- \(D\) è la devianza.
Poiché i GLM utilizzano la famiglia esponenziale di distribuzioni, la
devianza assume una forma specifica per diverse distribuzioni.
Formule della Verosimiglianza:
Modello Normale: La verosimiglianza nel caso di
una distribuzione normale è definita dalla densità di probabilità della
distribuzione normale. Per una singola osservazione, la formula è: \[ L(y_i | \mu_i, \sigma^2) =
\frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(y_i -
\mu_i)^2}{2\sigma^2}\right) \]
Dove:
- \(y_i\) è l’osservazione
i-esima.
- \(\mu_i\) è il valore atteso della
variabile di risposta i-esima.
- \(\sigma^2\) è la varianza.
Modello di Poisson: La verosimiglianza nel caso
di una distribuzione di Poisson è definita come segue: \[ L(y_i | \lambda_i) = \frac{\lambda_i^{y_i}
\exp(-\lambda_i)}{y_i!} \]
Dove:
- \(y_i\) è l’osservazione
i-esima.
- \(\lambda_i\) è il valore atteso
della variabile di risposta i-esima.
La devianza può essere interpretata come una misura della discrepanza
tra il modello fitted e il modello null. Un valore di devianza più basso
indica una migliore adattabilità del modello ai dati. Tuttavia, poiché
la devianza è una misura assoluta, è spesso utilizzato il concetto di
devianza residua, che è la devianza divisa per il numero di gradi di
libertà del modello. Questo consente un confronto più equo tra modelli
con differenti complessità.
Nel contesto dei GLM, la devianza è spesso scomposta in tre
componenti principali:
Modello Fitted Deviance (\(D_{\text{fitted}}\)): Misura la discrepanza
tra il modello fitted e i dati osservati.
Null Deviance (\(D_{\text{null}}\)): Misura la discrepanza
tra il modello null e i dati osservati.
Residual Deviance (\(D_{\text{residual}}\)): Rappresenta la
devianza residua, cioè la discrepanza non spiegata dal modello
fitted.
L’utilizzo di queste componenti permette di comprendere come la
devianza è distribuita tra il modello fitted, il modello null e la
devianza residua.
Il test di devianza è spesso utilizzato per confrontare modelli
alternativi. La differenza nella devianza tra due modelli segue
approssimativamente una distribuzione chi-quadro sotto l’ipotesi nulla
che i due modelli siano equivalenti. Questo test può essere utilizzato
per valutare l’aggiunta di predittori al modello o per confrontare
modelli con differenti specifiche di distribuzione della risposta.
Esempio di Devianza:
# Carichiamo un dataset di esempio in R
data(mtcars)
# Creiamo un modello di Poisson
model_poisson <- glm(vs ~ wt + hp, family = poisson, data = mtcars)
# Calcoliamo la devianza
deviance_value <- deviance(model_poisson)
cat("Devianza del Modello di Poisson:", deviance_value, "\n")
Devianza del Modello di Poisson: 9.969627
In questo esempio, calcoliamo e visualizziamo la devianza residua di
un modello di Poisson.
Residui
Nei GLM, i residui svolgono un ruolo cruciale nel valutare
l’adattamento del modello ai dati e nel verificare la validità delle
ipotesi dietro il modello. A differenza dei Modelli Lineari (LM), i
residui nei GLM sono calcolati considerando la distribuzione della
risposta specifica del modello.
- Misurare la Bontà di Adattamento:
- I residui nei GLM sono utilizzati per valutare la bontà di
adattamento del modello. Se il modello si adatta bene ai dati, ci si
aspetta che i residui abbiano una distribuzione che riflette la
distribuzione della risposta specificata nel GLM.
- Indicazioni sulla Struttura dei Dati:
- Nei GLM, la scelta della distribuzione della risposta e della
funzione di legame può variare in base alla natura dei dati. I residui
forniscono indicazioni sulla struttura dei dati e sulla validità delle
ipotesi del modello.
- Diagnosticare Devianza:
- La devianza, una misura della differenza tra il modello completo e
uno più semplice, può essere diagnosticata attraverso i residui. Residui
devianti e standardized deviance residuals sono spesso utilizzati per
individuare modelli non adatti ai dati.
Le principali differenze tra i residui nei GLM e nei LM riguardano la
distribuzione della risposta e la funzione di legame.
- Distribuzione della Risposta:
- Nei GLM, i residui sono calcolati tenendo conto della distribuzione
della risposta specificata nel modello. Ad esempio, nei modelli di
Poisson, i residui devono adattarsi alla distribuzione di Poisson.
- Nei LM, i residui sono basati sull’assunzione che la risposta sia
distribuita normalmente.
- Funzione di Legame:
- La funzione di legame nei GLM determina come il valore atteso della
risposta è collegato alla combinazione lineare dei predittori. La scelta
della funzione di legame influenza i residui.
- Nei LM, la funzione di legame è identità, e i residui riflettono
semplicemente la differenza tra i valori osservati e quelli
previsti.
Esempio di Calcolo dei Residui in un Modello
GLM:
suppressWarnings({
# Carichiamo un dataset di esempio in R con una distribuzione di Poisson
data(faithful, package = "datasets")
# Creiamo un modello di Poisson
modello_poisson <- glm(eruptions ~ waiting, family = poisson, data = faithful)
# Calcoliamo i residui devianti
residui_devianti <- residuals(modello_poisson, type = "deviance")
# Visualizziamo i primi 10 residui devianti
head(residui_devianti)
})
1 2 3 4 5 6
-0.2147663 -0.2970575 -0.1293332 -0.2561309 -0.0479040 0.3822210
I residui devianti riflettono le differenze tra i valori osservati e
quelli previsti in termini della devianza del modello. Un residuo
deviante elevato indica che l’osservazione contribuisce in modo
significativo alla devianza complessiva del modello, indicando
un’eventuale influenza o deviazione dal modello.
- Residui positivi indicano che l’osservazione ha contribuito più del
previsto alla devianza.
- Residui negativi indicano che l’osservazione ha contribuito meno del
previsto alla devianza.
- Residui pari a zero indicano una perfetta adattabilità
dell’osservazione al modello.
Esempio:
Per questo esempio, useremo il dataset di esempio “mtcars” di R per
creare un modello di Poisson utilizzando un modello generalizzato
lineare (GLM). Lo scopo del modello sarà prevedere il numero di cilindri
(“cyl”) in base alle altre variabili presenti nel dataset.
# Caricamento del dataset "mtcars"
data(mtcars)
# Esploriamo le prime righe del dataset
head(mtcars)
# Creiamo un modello di Poisson per prevedere il numero di cilindri in base alle altre variabili
modello_glm <- glm(cyl ~ mpg + disp + hp + drat + wt + qsec + vs + am + gear + carb,
data = mtcars, family = poisson)
# Visualizziamo il summary del modello
summary(modello_glm)
Call:
glm(formula = cyl ~ mpg + disp + hp + drat + wt + qsec + vs +
am + gear + carb, family = poisson, data = mtcars)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.42777 -0.16289 0.01851 0.15996 0.40340
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 3.1253653 2.3664672 1.321 0.187
mpg -0.0058390 0.0351590 -0.166 0.868
disp 0.0006115 0.0025727 0.238 0.812
hp 0.0002488 0.0033108 0.075 0.940
drat -0.0981988 0.2466800 -0.398 0.691
wt -0.0366284 0.3070279 -0.119 0.905
qsec -0.0406992 0.1219151 -0.334 0.739
vs -0.1092921 0.3282386 -0.333 0.739
am -0.1126824 0.3368595 -0.335 0.738
gear -0.0517634 0.2304110 -0.225 0.822
carb 0.0280157 0.1270379 0.221 0.825
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 16.574 on 31 degrees of freedom
Residual deviance: 1.310 on 21 degrees of freedom
AIC: 139.97
Number of Fisher Scoring iterations: 4
# Analizziamo le variabili indipendenti
par(mfrow = c(2, 2))
plot(modello_glm)

# Eseguiamo l'analisi della varianza (ANOVA)
anova_result <- anova(modello_glm, test = "Chi")
# Visualizziamo la tabella ANOVA
print(anova_result)
Analysis of Deviance Table
Model: poisson, link: log
Response: cyl
Terms added sequentially (first to last)
Df Deviance Resid. Df Resid. Dev Pr(>Chi)
NULL 31 16.5743
mpg 1 12.2921 30 4.2822 0.0004549 ***
disp 1 1.1779 29 3.1043 0.2777770
hp 1 0.3231 28 2.7812 0.5697385
drat 1 0.3586 27 2.4225 0.5492712
wt 1 0.2091 26 2.2135 0.6475086
qsec 1 0.4558 25 1.7577 0.4996039
vs 1 0.1329 24 1.6248 0.7154335
am 1 0.2440 23 1.3808 0.6213230
gear 1 0.0221 22 1.3587 0.8817565
carb 1 0.0487 21 1.3100 0.8253848
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Calcoliamo l'R-squared del modello
r_squared <- 1 - (modello_glm$deviance / modello_glm$null.deviance)
cat("R-squared:", r_squared, "\n")
R-squared: 0.9209632
# Effettuiamo previsioni su nuovi dati (per esempio, le prime 5 osservazioni del dataset)
nuovi_dati <- mtcars[1:5, ]
previsioni <- predict(modello_glm, newdata = nuovi_dati, type = "response")
cat("Previsioni per le prime 5 osservazioni:\n", previsioni, "\n")
Previsioni per le prime 5 osservazioni:
5.879263 5.693355 4.305739 5.683563 7.787923
In questo esempio, abbiamo creato un modello di Poisson utilizzando
il numero di cilindri come variabile dipendente e le altre variabili del
dataset “mtcars” come variabili indipendenti. Successivamente, abbiamo
eseguito un’analisi completa del modello, compresi il summary, la
visualizzazione delle variabili indipendenti, l’analisi della varianza
(ANOVA), il calcolo dell’R-squared e la previsione su nuovi dati.
[[Torna all’ Indice]]
LS0tCnRpdGxlOiAiUmlhc3N1bnRvIEFuYWxpc2kgUHJlZGl0dGl2YSIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogIlNpbW9uZSBEaW5hdG8iCmRhdGU6ICJEYXRhIGRpIENyZWF6aW9uZTogMjAyMy0xMC0yMCIKdmVyc2lvbjogIlZlcnNpb25lOiAwLjgiCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiBzZW50ZW5jZQotLS0KCiMgSW50cm9kdXppb25lCgpRdWVzdG8gZG9jdW1lbnRvIGZvcm5pc2NlIHVuJ2FtcGlhIHBhbm9yYW1pY2Egc3VsIGNvcnNvIGRpIEFuYWxpc2kgUHJlZGl0dGl2YSBkaSBDYScgRm9zY2FyaSAoQ1QwNDI5KSBkZWxsJ2Fubm8gMjAyMy8yMDI0LgpOZWwgY29yc28gZGVsIGRvY3VtZW50bywgZXNwbG9yZXJlbW8gdmFyaSBhcmdvbWVudGkgcmlndWFyZGFudGkgbCdBbmFsaXNpIFByZWRpdHRpdmEsIGNvbXByZXNpIEFub3ZhLCBSZXNpZHVpLCBGb3JtdWxlLCBDb3JyZWxhemlvbmUgdHJhIHZhcmlhYmlsaSwgUHJlZGljdCwgbCd1dGlsaXp6byBkaSBwacO5IG1vZGVsbGksIGUgY29tZSBzZWxlemlvbmFyZSBsZSB2YXJpYWJpbGkgYWxsJ2ludGVybm8gZGkgdW4gbW9kZWxsby4KCkwnb2JpZXR0aXZvIGRpIHF1ZXN0byBkb2N1bWVudG8gw6ggZ3VpZGFydGkgYXR0cmF2ZXJzbyBpIGNvbmNldHRpIGNoaWF2ZSBlIGxlIHByYXRpY2hlIG5lbGwnQW5hbGlzaSBQcmVkaXR0aXZhLCBjb24gdW4gZm9jdXMgc3VsbCd1dGlsaXp6byBkZWwgbGluZ3VhZ2dpbyBkaSBwcm9ncmFtbWF6aW9uZSBSIHBlciBhcHBsaWNhcmUgcXVlc3RlIHRlY25pY2hlLgpTcGVybyBjaGUgcXVlc3RvIGRvY3VtZW50byB0aSBhaXV0aSBhIGNvbXByZW5kZXJlIG1lZ2xpbyBxdWVzdGEgbWF0ZXJpYSBkaSBzdHVkaW8gYWwgZmluZSBkaSBzdXBlcmFyZSBsJ2VzYW1lLgoKIyMjIEluZGljZQoKLSAgIFtSZWdyZXNzaW9uZSBMaW5lYXJlXQogICAgLSAgIFtBbmFsaXNpIGRlaSByZXNpZHVpXQogICAgLSAgIFtTY29tcG9zaXppb25lIFNvbW1hIERpIFF1YWRyYXRpXQogICAgLSAgIFtQcmVkaXppb25lIE90dGltYWxlXQogICAgLSAgIFtDb3ZhcmlhbnphIGUgQ29ycmVsYXppb25lIEVtcGlyaWNhXQotICAgW1JlZ3Jlc3Npb25lIExpbmVhcmUgTXVsdGlwbGFdCiAgICAtICAgW0FwcHJvY2lvIE1hdHJpY2lhbGVdCiAgICAtICAgW0ludGVycHJldGF6aW9uZSBHZW9tZXRyaWNhXQogICAgLSAgIFtEaXN0cmlidXppb25lIEYgJiBBbm92YSBUYWJsZV0KICAgIC0gICBbTW9kZWxsaSBOaWRpZmljYXRpXQogICAgLSAgIFtTZWxlemlvbmUgZGVsbGUgdmFyaWFiaWxpXQogICAgLSAgIFtQcmVkaXppb25pIENhdGVnb3JpY2hlXQogICAgLSAgIFtDb250cm9sbG8gZGVsIE1vZGVsbG9dCiAgICAtICAgW1RyYW5zZm9ybWF6aW9uaV0KICAgIC0gICBbTXVsdGljb2xsaW5lYXJpdMOgXQogICAgLSAgIFtQdW50aSBJbmZsdWVudGldCi0gICBbTW9kZWxsaSBMaW5lYXJpIEdlbmVyYWxpenphdGldCiAgICAtICAgW0RldmlhbnphXQogICAgLSAgIFtSZXNpZHVpXQoKIyBSZWdyZXNzaW9uZSBMaW5lYXJlCgpMYSBSZWdyZXNzaW9uZSBMaW5lYXJlIChMUikgw6ggdW5hIHRlY25pY2Egc3RhdGlzdGljYSBjaGUgdmllbmUgdXRpbGl6emF0YSBwZXIgc3R1ZGlhcmUgbGEgcmVsYXppb25lIHRyYSBkdWUgbyBwacO5IHZhcmlhYmlsaSBxdWFudGl0YXRpdmUuIElsIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgbGluZWFyZSBhc3N1bWUgY2hlIGxhIHZhcmlhYmlsZSBkaXBlbmRlbnRlLCBjaGUgc2kgZGVzaWRlcmEgcHJlZGlyZSwgc2lhIHVuYSBmdW56aW9uZSBsaW5lYXJlIGRlbGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkuCgpJbCBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUgZmEgbGUgc2VndWVudGkgYXNzdW56aW9uaToKCiogKipMaW5lYXJpdMOgOioqIExhIHJlbGF6aW9uZSB0cmEgbGEgdmFyaWFiaWxlIGRpcGVuZGVudGUgZSBsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpIMOoIGxpbmVhcmUuCiogKipOb3JtYWxpdMOgOioqIEkgcmVzaWR1aSBzb25vIGRpc3RyaWJ1aXRpIG5vcm1hbG1lbnRlLgoqICoqSW5kaXBlbmRlbnphOioqIEkgcmVzaWR1aSBzb25vIGluZGlwZW5kZW50aSB0cmEgbG9yby4KKiAqKkV0ZXJvc2NoZWRhc3RpY2l0w6A6KiogTGEgdmFyaWFuemEgZGVpIHJlc2lkdWkgw6ggY29zdGFudGUuCgpMJ2VxdWF6aW9uZSBkZWwgbW9kZWxsbyBkaSByZWdyZXNzaW9uZSBsaW5lYXJlIHNlbXBsaWNlIMOoIGxhIHNlZ3VlbnRlOgoKCiQkIHkgPSBhICsgYnggJCQKCgpkb3ZlOgoKKiB5IMOoIGxhIHZhcmlhYmlsZSBkaXBlbmRlbnRlCiogYSDDqCBsJ2ludGVyY2V0dGEKKiBiIMOoIGlsIGNvZWZmaWNpZW50ZSBhbmdvbGFyZQoqIHggw6ggbGEgdmFyaWFiaWxlIGluZGlwZW5kZW50ZQoKTCdpbnRlcmNldHRhIHJhcHByZXNlbnRhIGlsIHZhbG9yZSBtZWRpbyBkaSB5IHF1YW5kbyB4IMOoIHVndWFsZSBhIDAuIElsIGNvZWZmaWNpZW50ZSBhbmdvbGFyZSByYXBwcmVzZW50YSBsYSB2YXJpYXppb25lIGRpIHkgcGVyIG9nbmkgdW5pdMOgIGRpIHZhcmlhemlvbmUgZGkgeC4KCiMjIyBBbmFsaXNpIGRlaSByZXNpZHVpCgpTZXJ2ZSBhIHZlcmlmaWNhcmUgc2UgaWwgbW9kZWxsbyBzb2RkaXNmYSBsZSBhc3N1bnppb25pIGRlbGxhIHJlZ3Jlc3Npb25lIGUgcGVyIGlkZW50aWZpY2FyZSBldmVudHVhbGkgcGF0dGVybiBvIHByb2JsZW1pIG5laSBkYXRpLgoKKipFc2VtcGlvIDE6KioKCmBgYHtyfQojIEdlbmVyaWFtbyBkYXRpIGNhc3VhbGkgY29uIHJlc2lkdWkgbm9ybWFsbWVudGUgZGlzdHJpYnVpdGkKc2V0LnNlZWQoMTIzKQp4IDwtIDE6MTAwCnkgPC0gMiAqIHggKyBybm9ybSgxMDApCgojIEFkYXR0aWFtbyB1biBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lCm1vZGVsIDwtIGxtKHkgfiB4KQoKIyBFZmZldHR1aWFtbyBsJ2FuYWxpc2kgZGVpIHJlc2lkdWkKUmVzaWR1YWxzIDwtIHJlc2lkdWFscyhtb2RlbCkKCiMgQ3JlaWFtbyB1biBncmFmaWNvIGRlaSByZXNpZHVpCnBsb3QoeCwgUmVzaWR1YWxzLCBtYWluID0gIkRpc3RyaWJ1emlvbmUgTm9ybWFsZSBkZWkgUmVzaWR1aSIseGxhYiA9ICJYIiwgeWxhYiA9ICJSZXNpZHVpIikKYWJsaW5lKGggPSAwLCBjb2wgPSAicmVkIikKYGBgCgpJbiBxdWVzdG8gY2FzbywgaSByZXNpZHVpIHNlZ3Vvbm8gdW5hIGRpc3RyaWJ1emlvbmUgbm9ybWFsZSwgaWwgY2hlIMOoIHVuIHJpc3VsdGF0byBpZGVhbGUgcGVyIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgbGluZWFyZS4KUXVhbmRvIGRpY2lhbW8gY2hlIGkgcmVzaWR1aSBoYW5ubyB1bmEgZGlzdHJpYnV6aW9uZSBub3JtYWxlLCBzaWduaWZpY2EgY2hlIGkgcmVzaWR1aSBzZWd1b25vIHVuYSBkaXN0cmlidXppb25lIGEgZm9ybWEgZGkgY2FtcGFuYSwgY29uIHVuYSBtZWRpYSBkaSB6ZXJvIGUgdW5hIHZhcmlhbnphIGNvc3RhbnRlLgpRdWVzdGEgw6ggdW4naW1wb3J0YW50ZSBhc3N1bnppb25lIG5laSBtb2RlbGxpIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUsIGluIHF1YW50byBpbmRpY2EgY2hlIGdsaSBlcnJvcmkgY2FzdWFsaSBuZWwgbW9kZWxsbyBzb25vIGRpc3RyaWJ1aXRpIGluIG1vZG8gc2ltbWV0cmljbyBpbnRvcm5vIGEgemVybyBlIG5vbiBtb3N0cmFubyBhbGN1biB0aXBvIGRpIHRlbmRlbnphIHNpc3RlbWljYS4KU2UgcXVlc3RhIGFzc3VuemlvbmUgw6ggc29kZGlzZmF0dGEsIGkgdGVzdCBkaSBzaWduaWZpY2F0aXZpdMOgIGRlaSBjb2VmZmljaWVudGkgZGVsIG1vZGVsbG8gZSBsZSBzdGltZSBkaSBpbnRlcnZhbGxvIGRpIGNvbmZpZGVuemEgc2FyYW5ubyBhZmZpZGFiaWxpLgoKKipFc2VtcGlvIDI6KioKCmBgYHtyfQojIEdlbmVyaWFtbyBkYXRpIGNhc3VhbGkgY29uIHJlc2lkdWkgY2hlIHNlZ3Vvbm8gdW5hIGRpc3RyaWJ1emlvbmUgYSBVCnNldC5zZWVkKDQ1NikKeCA8LSAxOjEwMAp5IDwtIDIgKiB4XjIgKyBybm9ybSgxMDApCnlbNTA6NjBdIDwtIHlbNTA6NjBdICsgMTAgICMgSW50cm9kdWNpYW1vIHVuIGVmZmV0dG8gYSBVIG5laSBkYXRpCgojIEFkYXR0aWFtbyB1biBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lCm1vZGVsIDwtIGxtKHkgfiB4KQoKIyBFZmZldHR1aWFtbyBsJ2FuYWxpc2kgZGVpIHJlc2lkdWkKcmVzaWR1YWxzIDwtIHJlc2lkdWFscyhtb2RlbCkKCiMgQ3JlaWFtbyB1biBncmFmaWNvIGRlaSByZXNpZHVpCnBsb3QoeCwgcmVzaWR1YWxzLCBtYWluID0gIkRpc3RyaWJ1emlvbmUgYSBVIGRlaSBSZXNpZHVpIiwgeGxhYiA9ICJYIiwgeWxhYiA9ICJSZXNpZHVpIikKYWJsaW5lKGggPSAwLCBjb2wgPSAicmVkIikKYGBgCgpJbiBxdWVzdG8gY2FzbywgaSByZXNpZHVpIG1vc3RyYW5vIHVuIGVmZmV0dG8gYSBVLCBpbmRpY2FuZG8gdW5hIHZpb2xhemlvbmUgZGVsbCdhc3N1bnppb25lIGRpIG9tb3NjaGVkYXN0aWNpdMOgKGkgcmVzaWR1aSBub24gbW9zdHJhbm8gdW4gYXVtZW50byBvIHVuYSBkaW1pbnV6aW9uZSBzaXN0ZW1hdGljYSBuZWxsYSBkaXNwZXJzaW9uZSBhbCB2YXJpYXJlIGRlaSB2YWxvcmkgZGVsbGUgdmFyaWFiaWxpIGluZGlwZW5kZW50aSkuCgoqKkVzZW1waW8gMzoqKgoKYGBge3J9CiMgR2VuZXJpYW1vIGRhdGkgY2FzdWFsaSBjb24gb3V0bGllciBuZWkgcmVzaWR1aQpzZXQuc2VlZCg3ODkpCnggPC0gMToxMDAKeSA8LSAyICogeCArIHJub3JtKDEwMCkKeVtjKDIwLCA4NSldIDwtIHlbYygyMCwgODUpXSArIDIwICAjIEFnZ2l1bmdpYW1vIG91dGxpZXIgbmVpIGRhdGkKCiMgQWRhdHRpYW1vIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUKbW9kZWwgPC0gbG0oeSB+IHgpCgojIEVmZmV0dHVpYW1vIGwnYW5hbGlzaSBkZWkgcmVzaWR1aQpyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKG1vZGVsKQoKIyBDcmVpYW1vIHVuIGdyYWZpY28gZGVpIHJlc2lkdWkKcGxvdCh4LCByZXNpZHVhbHMsIG1haW4gPSAiUHJlc2VuemEgZGkgT3V0bGllciBuZWkgUmVzaWR1aSIsIHlsYWIgPSAiUmVzaWR1aSIsIHhsYWIgPSAiWCIpCmFibGluZShoID0gMCwgY29sID0gInJlZCIpCmBgYAoKSW4gcXVlc3RvIGNhc28sIGkgcmVzaWR1aSBtb3N0cmFubyBsYSBwcmVzZW56YSBkaSBvdXRsaWVyIGV2aWRlbnRpLCBjaGUgcG9zc29ubyBpbmZsdWVuemFyZSBpbiBtb2RvIHNpZ25pZmljYXRpdm8gbGEgc3RpbWEgZGVpIGNvZWZmaWNpZW50aSBkZWwgbW9kZWxsby4KR2xpIG91dGxpZXIgcG9zc29ubyBjb21wb3J0YXJlIHByb2JsZW1pIG5laSBtb2RlbGxpIHN0YXRpc3RpY2ksIHNwZWNpYWxtZW50ZSBuZWkgbW9kZWxsaSBkaSByZWdyZXNzaW9uZSwgcGVyY2jDqSBwb3Nzb25vIGluZmx1ZW56YXJlIG5vdGV2b2xtZW50ZSBpIHJpc3VsdGF0aS4KQWQgZXNlbXBpbywgcG9zc29ubyBpbmZsdWVuemFyZSBsYSBzdGltYSBkZWkgY29lZmZpY2llbnRpIGRlbCBtb2RlbGxvIGUgcmVuZGVyZSBpbCBtb2RlbGxvIG1lbm8gYWZmaWRhYmlsZS4KCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIFNjb21wb3NpemlvbmUgU29tbWEgRGkgUXVhZHJhdGkKCkxhICJkZWNvbXBvc2l0aW9uIG9mIHN1bSBvZiBzcXVhcmVzIiDDqCB1biBjb25jZXR0byBmb25kYW1lbnRhbGUgbmVsbCdhbmFsaXNpIGRlbGxhIHZhcmlhbnphIChBTk9WQSkgZSBuZWxsYSByZWdyZXNzaW9uZSBzdGF0aXN0aWNhLgpRdWVzdGEgdGVjbmljYSBhaXV0YSBhIHNjb21wb3JyZSBsYSB2YXJpYW56YSB0b3RhbGUgb3NzZXJ2YXRhIGluIHVuIGluc2llbWUgZGkgZGF0aSBpbiBkaXZlcnNlIGNvbXBvbmVudGksIGNvbnNlbnRlbmRvIGRpIGNvbXByZW5kZXJlIHF1YW50byBkZWxsYSB2YXJpYW56YSBwdcOyIGVzc2VyZSBhdHRyaWJ1aXRvIGEgdmFyaSBmYXR0b3JpIG8gZXJyb3JpIHJlc2lkdWkuCkxhIGZvcm11bGEgY2hpYXZlIGluIHF1ZXN0byBjb250ZXN0byDDqDoKCiQkIFZhcmlhbnphIFRvdGFsZSA9IFZhcmlhbnphIFNwaWVnYXRhICsgVmFyaWFuemEgUmVzaWR1YSAkJAoKRG92ZToKCi0gICBWYXJpYW56YSBUb3RhbGUgw6ggbGEgdmFyaWFuemEgY29tcGxlc3NpdmEgZGVpIGRhdGksIGNpb8OoIHF1YW50byBpIGRhdGkgdmFyaWFubyBpbiBnZW5lcmFsZS4KCi0gICBWYXJpYW56YSBTcGllZ2F0YSByYXBwcmVzZW50YSBsYSB2YXJpYW56YSBkb3Z1dGEgYWwgbW9kZWxsbyBvIGFpIGZhdHRvcmkgZXNhbWluYXRpIChzcGllZ2F0aSBkYWxsYSB2YXJpYWJpbGUgaW5kaXBlbmRlbnRlIG5lbCBjb250ZXN0byBkZWxsYSByZWdyZXNzaW9uZSkuCgotICAgVmFyaWFuemEgUmVzaWR1YSDDqCBsYSB2YXJpYW56YSBub24gc3BpZWdhdGEgZGFsIG1vZGVsbG8gbyBkYWkgZmF0dG9yaSBlZCDDqCBhc3NvY2lhdGEgYWxsJ2Vycm9yZSByZXNpZHVvLCBvdnZlcm8gbGEgZGlmZmVyZW56YSB0cmEgaSB2YWxvcmkgb3NzZXJ2YXRpIGUgcXVlbGxpIHByZXZpc3RpIGRhbCBtb2RlbGxvLgoKTmVsIGNvbnRlc3RvIGRlbGxhIHJlZ3Jlc3Npb25lLCBwdW9pIHJhcHByZXNlbnRhcmUgbGEgZGVjb21wb3NpemlvbmUgZGVsbGEgc29tbWEgZGVpIHF1YWRyYXRpIGNvbWUgc2VndWU6CgokJCBTU1QgPSBTU1IgKyBTU0UgJCQKCi0gICBTU1QgKFN1bSBvZiBTcXVhcmVzIFRvdGFsKSByYXBwcmVzZW50YSBsYSBzb21tYSBkZWkgcXVhZHJhdGkgdG90YWxlIGVkIMOoIGxhIHZhcmlhbnphIGRlaSBkYXRpIG9zc2VydmF0aSByaXNwZXR0byBhbGxhIGxvcm8gbWVkaWEuCgotICAgU1NSIChTdW0gb2YgU3F1YXJlcyBSZWdyZXNzaW9uKSByYXBwcmVzZW50YSBsYSB2YXJpYW56YSBzcGllZ2F0YSBkYWwgbW9kZWxsbyBvIGRhbGxhIHZhcmlhYmlsZSBpbmRpcGVuZGVudGUuCgotICAgU1NFIChTdW0gb2YgU3F1YXJlcyBFcnJvcikgcmFwcHJlc2VudGEgbGEgdmFyaWFuemEgcmVzaWR1YSwgb3NzaWEgbGEgdmFyaWFuemEgbm9uIHNwaWVnYXRhIGRhbCBtb2RlbGxvLgoKUGVyIHZhbHV0YXJlIGwnZWZmaWNpZW56YSBkZWwgdHVvIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUsIGRvdnJlc3RpIGd1YXJkYXJlIGxhIHByb3Bvcnppb25lIGRpIHF1ZXN0YSB2YXJpYW56YSBzcGllZ2F0YSBkYWwgdHVvIG1vZGVsbG8gKFNTUikuCkluIGdlbmVyYWxlLCB2dW9pIG1hc3NpbWl6emFyZSBsYSBwcm9wb3J6aW9uZSBzcGllZ2F0YSBlIG1pbmltaXp6YXJlIGxhIHByb3Bvcnppb25lIG5vbiBzcGllZ2F0YSAoU1NFKS4KUGVydGFudG8sIHB1bnRpIGEgbWluaW1penphcmUgU1NFLgoKYGBge3J9CmRhdGEgPC0gZGF0YS5mcmFtZShYID0gYygxLCAyLCAzLCA0LCA1KSwgWSA9IGMoMywgNSwgNiwgOCwgMTApKQptZWFuX1kgPC0gbWVhbihkYXRhJFkpClNTVCA8LSBzdW0oKGRhdGEkWSAtIG1lYW5fWSleMikKCiMgQWRhdHRhIGlsIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgbGluZWFyZQptb2RlbCA8LSBsbShZIH4gWCwgZGF0YSA9IGRhdGEpCgojIENhbGNvbGEgbGEgU1NSClNTUiA8LSBzdW0oKHByZWRpY3QobW9kZWwpIC0gbWVhbl9ZKV4yKQoKIyBDYWxjb2xhIGxhIFNTRQpTU0UgPC0gc3VtKG1vZGVsJHJlc2lkdWFsc14yKQoKUl9zcXVhcmVkIDwtIFNTUiAvIFNTVAoKIyBFcXVpdmFsZSBhIGZhcmUgc3VtbWFyeShtb2RlbCkKUl9zcXVhcmVkCmBgYAoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIyMgUHJlZGl6aW9uZSBPdHRpbWFsZQoKTCciT3B0aW1hbCBQcmVkaWN0aW9uIiAgcmlndWFyZGEgbGEgZGV0ZXJtaW5hemlvbmUgZGkgdW4gbW9kZWxsbyBwcmVkaXR0aXZvIGNoZSBzaWEgaWwgbWlnbGlvcmUgcG9zc2liaWxlIGluIHRlcm1pbmkgZGkgYWNjdXJhdGV6emEgbmVsIHByZXZlZGVyZSBnbGkgZXZlbnRpIGZ1dHVyaS4KCkwnb2JpZXR0aXZvIHByaW5jaXBhbGUgw6ggdHJvdmFyZSBpbCBtb2RlbGxvIGNoZSBtYXNzaW1penphIGxhIHByZWNpc2lvbmUgZGVsbGUgcHJldmlzaW9uaSwgbWluaW1penphbmRvIGwnZXJyb3JlIGRpIHByZXZpc2lvbmUuCkNpIHNvbm8gdmFyaSBtZXRvZGkgZSB0ZWNuaWNoZSBwZXIgb3R0ZW5lcmUgbGEgcHJlZGl6aW9uZSBvdHRpbWFsZSwgYSBzZWNvbmRhIGRlbCBjb250ZXN0byBlIGRlaSBkYXRpIGRpc3BvbmliaWxpLgoKYGBge3J9CiMgQ2FyaWNhbWVudG8gZGVsIGRhdGFzZXQgImNhcnMiCmRhdGEoY2FycykKCiMgVmlzdWFsaXp6YXppb25lIGRlbGxlIHByaW1lIHJpZ2hlIGRlbCBkYXRhc2V0CmhlYWQoY2FycykKCiMgRGl2aWRpYW1vIGlsIGRhdGFzZXQgaW4gc2V0IGRpIGFkZGVzdHJhbWVudG8gZSBzZXQgZGkgdGVzdApzZXQuc2VlZCgxMjMpICAjIEltcG9zdGlhbW8gdW4gc2VlZCBwZXIgbGEgcmlwcm9kdWNpYmlsaXTDoApzYW1wbGVfaW5kaWNlcyA8LSBzYW1wbGUobnJvdyhjYXJzKSwgbnJvdyhjYXJzKSAqIDAuNykgICMgNzAlIGRhdGkgZGkgYWRkZXN0cmFtZW50bwp0cmFpbl9kYXRhIDwtIGNhcnNbc2FtcGxlX2luZGljZXMsIF0KdGVzdF9kYXRhIDwtIGNhcnNbLXNhbXBsZV9pbmRpY2VzLCBdCgojIEFkYXR0YW1lbnRvIGRpIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgbGluZWFyZQptb2RlbCA8LSBsbShkaXN0IH4gc3BlZWQsIGRhdGEgPSB0cmFpbl9kYXRhKQoKIyBQcmVkaXppb25pCnByZWRpY3Rpb25zIDwtIHByZWRpY3QobW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEpCgojIFZhbHV0YXppb25lIGRlbGxlIHByZXN0YXppb25pCnN1bW1hcnkobW9kZWwpCgojIEdyYWZpY28gZGVpIHJpc3VsdGF0aQpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdChkYXRhID0gdGVzdF9kYXRhLCBhZXMoeCA9IHNwZWVkLCB5ID0gZGlzdCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKwogIGdndGl0bGUoIlByZWRpemlvbmUgZGVsbGEgRGlzdGFuemEgZGkgQXJyZXN0byIpCgpgYGAKCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIENvdmFyaWFuemEgZSBDb3JyZWxhemlvbmUgRW1waXJpY2EKCkxhIGNvdmFyaWFuemEgZSBjb3JyZWxhemlvbmUgZW1waXJpY2Egc29ubyBtaXN1cmUgc3RhdGlzdGljaGUgdXRpbGl6emF0ZSBwZXIgcXVhbnRpZmljYXJlIGxhIHJlbGF6aW9uZSB0cmEgZHVlIHZhcmlhYmlsaSBpbiB1biBpbnNpZW1lIGRpIGRhdGkgb3NzZXJ2YXRpLgpRdWVzdGUgbWlzdXJlIHNvbm8gc3RyZXR0YW1lbnRlIGxlZ2F0ZSBlIHNvbm8gc3Blc3NvIHV0aWxpenphdGUgcGVyIGVzYW1pbmFyZSBsYSByZWxhemlvbmUgbGluZWFyZSB0cmEgZHVlIHZhcmlhYmlsaS4KCioqQ292YXJpYW56YSBFbXBpcmljYToqKgoKTGEgY292YXJpYW56YSBlbXBpcmljYSDDqCB1bmEgbWlzdXJhIGRlbGxhIHRlbmRlbnphIGRpIGR1ZSB2YXJpYWJpbGkgYSB2YXJpYXJlIGluc2llbWUuCkluZGljYSBzZSBsZSBkdWUgdmFyaWFiaWxpIGNyZXNjb25vIG8gZGltaW51aXNjb25vIHNpbXVsdGFuZWFtZW50ZSAoY292YXJpYW56YSBwb3NpdGl2YSkgbyBzZSB1bmEgYXVtZW50YSBtZW50cmUgbCdhbHRyYSBkaW1pbnVpc2NlIChjb3ZhcmlhbnphIG5lZ2F0aXZhKS4KTGEgZm9ybXVsYSBwZXIgY2FsY29sYXJlIGxhIGNvdmFyaWFuemEgZW1waXJpY2EgdHJhIGR1ZSB2YXJpYWJpbGkgWCBlIFkgaW4gdW4gc2V0IGRpIGRhdGkgw6ggZGF0YSBkYToKCiQkICBDb3YoWCxZKSA9IFxmcmFjezF9e24tMX0gXHN1bV97aSA9IDF9Xm4geyhYX2kgLSBcb3ZlcmxpbmV7WH0pKFlfaSAtIFxvdmVybGluZXtZfSl9ICQkCgoqKkNvcnJlbGF6aW9uZSBFbXBpcmljYToqKgoKTGEgY29ycmVsYXppb25lIGVtcGlyaWNhIMOoIHVuYSB2ZXJzaW9uZSBzdGFuZGFyZGl6emF0YSBkZWxsYSBjb3ZhcmlhbnphIGVtcGlyaWNhIGUgbWlzdXJhIGxhIGZvcnphIGUgbGEgZGlyZXppb25lIGRpIHVuYSByZWxhemlvbmUgbGluZWFyZSB0cmEgZHVlIHZhcmlhYmlsaS4KTGEgY29ycmVsYXppb25lIGVtcGlyaWNhIMOoIHNlbXByZSBjb21wcmVzYSB0cmEgLTEgZSAxLgpMYSBmb3JtdWxhIHBlciBjYWxjb2xhcmUgbGEgY29ycmVsYXppb25lIGVtcGlyaWNhIHRyYSBkdWUgdmFyaWFiaWxpIFggZSBZIMOoIGRhdGEgZGE6CgokJCAgQ29yKFgsWSkgPSBcZnJhY3tDb3YoWCxZKX17U19YIFxjZG90IFNfWX0gJCQKCkxlIG1pc3VyZSBkaSBjb3ZhcmlhbnphIGVtcGlyaWNhIGUgY29ycmVsYXppb25lIGVtcGlyaWNhIHNvbm8gdXRpbGl6emF0ZSBwZXIgZXNhbWluYXJlIGxhIHJlbGF6aW9uZSB0cmEgdmFyaWFiaWxpIGluIHVuIHNldCBkaSBkYXRpIGUgc29ubyBwYXJ0aWNvbGFybWVudGUgdXRpbGkgbmVsbCdhbmFsaXNpIHN0YXRpc3RpY2EgZSBuZWxsJ2FwcHJlbmRpbWVudG8gYXV0b21hdGljbyBwZXIgdmFsdXRhcmUgbGUgYXNzb2NpYXppb25pIHRyYSBsZSB2YXJpYWJpbGkgcHJpbWEgZGkgY29zdHJ1aXJlIG1vZGVsbGkgcHJlZGl0dGl2aS4KTGEgY29ycmVsYXppb25lIGVtcGlyaWNhIMOoIHBpw7kgY29tdW5lbWVudGUgdXRpbGl6emF0YSBwZXJjaMOpIGZvcm5pc2NlIHVuYSBtaXN1cmEgc3RhbmRhcmRpenphdGEgZGVsbGEgcmVsYXppb25lIHRyYSB2YXJpYWJpbGkgZWQgw6ggbWVubyBpbmZsdWVuemF0YSBkYWxsJ3VuaXTDoCBkaSBtaXN1cmEuCgpJbCBjb2VmZmljaWVudGUgZGkgUGVhcnNvbiDDqCB1dGlsZSBwZXIgdmVkZXJlIHNlIGR1ZSB2YXJpYWJpbGkgaGFubm8gdW5hIGNvcnJlbGF6aW9uZSBsaW5lYXJlIG8gbWVuby4KUXVlc3RvIHBlcmNow6kgbm9uIHR1dHRlIGxlIHZhcmlhYmlsaSBjb3JyZWxhdGUgaGFubm8gdW5hIHJlbGF6aW9uZSBsaW5lYXJlLgoKRXNlbXBpbzoKCmBgYHtyfQojIEVzZW1waW8gZGF0aSBjYXN1YWxpCnNldC5zZWVkKDEyMykKeCA8LSBybm9ybSgxMDApICAjIFZhcmlhYmlsZSB4CnkgPC0gMiAqIHggKyBybm9ybSgxMDApICAjIFZhcmlhYmlsZSB5IChjb3JyZWxhdGEgYSB4KQoKIyBDYWxjb2xhIGxhIGNvcnJlbGF6aW9uZSBkaSBQZWFyc29uCmNvcnJlbGF0aW9uIDwtIGNvcih4LCB5KQoKIyBTdGFtcGEgaWwgdmFsb3JlIGRpIGNvcnJlbGF6aW9uZQpjYXQoIkNvcnJlbGF6aW9uZSBkaSBQZWFyc29uIHRyYSB4IGUgeToiLCBjb3JyZWxhdGlvbiwgIlxuIikKYGBgCgpJbiBxdWVzdG8gZXNlbXBpbywgc3RpYW1vIGdlbmVyYW5kbyBkYXRpIGNhc3VhbGkgcGVyIGxlIHZhcmlhYmlsaSB4IGUgeS4KTGEgdmFyaWFiaWxlIHkgw6ggY29zdHJ1aXRhIGNvbWUgdW5hIHRyYXNmb3JtYXppb25lIGxpbmVhcmUgZGkgeCBjb24gdW4gdGVybWluZSBkaSBlcnJvcmUgYWdnaXVudG8uClBvaSwgdXRpbGl6emlhbW8gbGEgZnVuemlvbmUgY29yKCkgcGVyIGNhbGNvbGFyZSBsYSBjb3JyZWxhemlvbmUgZGkgUGVhcnNvbiB0cmEgeCBlIHkuCgpVbiB2YWxvcmUgdmljaW5vIGEgMSBpbmRpY2EgdW5hIGNvcnJlbGF6aW9uZSBsaW5lYXJlIHBvc2l0aXZhIGZvcnRlLCB1biB2YWxvcmUgdmljaW5vIGEgLTEgaW5kaWNhIHVuYSBjb3JyZWxhemlvbmUgbGluZWFyZSBuZWdhdGl2YSBmb3J0ZSwgbWVudHJlIHVuIHZhbG9yZSB2aWNpbm8gYSAwIGluZGljYSB1bmEgc2NhcnNhIGNvcnJlbGF6aW9uZSBsaW5lYXJlIHRyYSBsZSBkdWUgdmFyaWFiaWxpLgoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIFJlZ3Jlc3Npb25lIExpbmVhcmUgTXVsdGlwbGEKCkxhICJNdWx0aXBsZSBMaW5lYXIgUmVncmVzc2lvbiIgKFJlZ3Jlc3Npb25lIExpbmVhcmUgTXVsdGlwbGEpIMOoIHVuYSB0ZWNuaWNhIGRpIG1vZGVsbGF6aW9uZSBzdGF0aXN0aWNhIHV0aWxpenphdGEgcGVyIGFuYWxpenphcmUgbGEgcmVsYXppb25lIHRyYSB1bmEgdmFyaWFiaWxlIGRpcGVuZGVudGUgKG8gdGFyZ2V0KSBlIGR1ZSBvIHBpw7kgdmFyaWFiaWxpIGluZGlwZW5kZW50aSAobyBwcmVkaXR0aXZlKS4KUXVlc3RhIHRlY25pY2EgZXN0ZW5kZSBsYSBzZW1wbGljZSByZWdyZXNzaW9uZSBsaW5lYXJlLCBjaGUgY29pbnZvbGdlIHNvbG8gdW5hIHZhcmlhYmlsZSBpbmRpcGVuZGVudGUsIGEgdW4gY29udGVzdG8gaW4gY3VpIHBpw7kgdmFyaWFiaWxpIGluZGlwZW5kZW50aSBzb25vIGNvaW52b2x0ZSBuZWwgbW9kZWxsby4KTGEgcmVncmVzc2lvbmUgbGluZWFyZSBtdWx0aXBsYSDDqCBhbXBpYW1lbnRlIHV0aWxpenphdGEgbmVsbCdhbmFsaXNpIHN0YXRpc3RpY2EgZSBuZWxsJ2FwcHJlbmRpbWVudG8gYXV0b21hdGljbyBwZXIgZmFyZSBwcmV2aXNpb25pIG8gY29tcHJlbmRlcmUgbGUgcmVsYXppb25pIGNvbXBsZXNzZSB0cmEgdmFyaWFiaWxpLgoKJCQgWSA9IFxiZXRhXzAgKyBcYmV0YV8xWF8xICsgLi4uICsgXGJldGFfblhfbiArIFxlcHNpbG9uICQkIEwnb2JpZXR0aXZvIHByaW5jaXBhbGUgw6ggc3RpbWFyZSBpIGNvZWZmaWNpZW50aSDOsiBpbiBtb2RvIGNoZSBpbCBtb2RlbGxvIHNpIGFkYXR0aSBtZWdsaW8gYWkgZGF0aSBvc3NlcnZhdGkuClF1ZXN0byB2aWVuZSBmYXR0byB1dGlsaXp6YW5kbyBtZXRvZGkgZGkgc3RpbWEsIGNvbWUgaWwgbWV0b2RvIGRlaSBtaW5pbWkgcXVhZHJhdGksIGNoZSBjZXJjYSBkaSBtaW5pbWl6emFyZSBsYSBzb21tYSBkZWkgcXVhZHJhdGkgZGVnbGkgZXJyb3JpIHJlc2lkdWkuCklsIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgdmllbmUgdmFsdXRhdG8gdXRpbGl6emFuZG8gbWV0cmljaGUgZGkgdmFsdXRhemlvbmUgZGVsbGUgcHJlc3RhemlvbmkgY29tZSBsJ2Vycm9yZSBxdWFkcmF0aWNvIG1lZGlvIChSTVNFKSwgaWwgY29lZmZpY2llbnRlIGRpIGRldGVybWluYXppb25lIChSLXNxdWFyZWQpIGUgYWx0cmkuCsOIIGltcG9ydGFudGUgZXNlZ3VpcmUgdGVzdCBkaSBzaWduaWZpY2F0aXZpdMOgIHN0YXRpc3RpY2EgcGVyIGkgY29lZmZpY2llbnRpIGRlbGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgcGVyIGRldGVybWluYXJlIHNlIGVzc2UgY29udHJpYnVpc2Nvbm8gc2lnbmlmaWNhdGl2YW1lbnRlIGFsIG1vZGVsbG8uCgpMYSByZWdyZXNzaW9uZSBsaW5lYXJlIG11bHRpcGxhIMOoIGJhc2F0YSBzdSBhbGN1bmUgYXNzdW56aW9uaSwgdHJhIGN1aSBsJ2luZGlwZW5kZW56YSBkZWdsaSBlcnJvcmksIGwnb21vc2NoZWRhc3RpY2l0w6AgKHZhcmlhbnphIGNvc3RhbnRlIGRlZ2xpIGVycm9yaSksIGxhIGxpbmVhcml0w6AgZGVsbGEgcmVsYXppb25lIGUgbGEgbm9ybWFsaXTDoCBkZWdsaSBlcnJvcmkuCgpgYGB7cn0KIyBDYXJpY2EgaWwgZGF0YXNldCBtdGNhcnMKZGF0YShtdGNhcnMpCgojIFZpc3VhbGl6emEgbGUgcHJpbWUgcmlnaGUgZGVsIGRhdGFzZXQKaGVhZChtdGNhcnMpCgojIEFkYXR0YW1lbnRvIGRlbCBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUgbXVsdGlwbGEKbW9kZWwgPC0gbG0obXBnIH4gd3QgKyBocCArIHFzZWMsIGRhdGEgPSBtdGNhcnMpCgojIFZpc3VhbGl6emEgdW4gcmllcGlsb2dvIGRlbCBtb2RlbGxvCnN1bW1hcnkobW9kZWwpCmBgYAoKSW4gc2ludGVzaSwgaWwgbW9kZWxsbyBkaSByZWdyZXNzaW9uZSBsaW5lYXJlIG11bHRpcGxhIHN1Z2dlcmlzY2UgY2hlIGlsIHBlc28gZGVsIHZlaWNvbG8gaW5mbHVlbnphIGlsIGNvbnN1bW8gZGkgY2FyYnVyYW50ZS4KTGEgcG90ZW56YSBkZWwgbW90b3JlIGUgaWwgdGVtcG8gZGkgYWNjZWxlcmF6aW9uZSBub24gc29ubyBzaWduaWZpY2F0aXZlIHBlciBsYSBzcGllZ2F6aW9uZSBkaSBxdWVzdG8gbW9kZWxsby4KTm9ub3N0YW50ZSBjacOyIGlsIG1vZGVsbG8gc3BpZWdhIGwnODMlIGRlaSBkZWxsYSB2YXJpYXppb25lIG5laSBjb25zdW1pIGRpIGNhcmJ1cmFudGUuCgpbVG9ybmEgYWxsJyBbSW5kaWNlXV0KCiMjIyBBcHByb2NpbyBNYXRyaWNpYWxlCgpMJ2FwcHJvY2NpbyBtYXRyaWNpYWxlIGFsbGEgcmVncmVzc2lvbmUgw6ggdW5hIGZvcm1hIGFsdGVybmF0aXZhIGRpIHJhcHByZXNlbnRhemlvbmUgZSByaXNvbHV6aW9uZSBkZWkgbW9kZWxsaSBkaSByZWdyZXNzaW9uZSwgaW5jbHVzYSBsYSByZWdyZXNzaW9uZSBsaW5lYXJlLgpRdWVzdG8gYXBwcm9jY2lvIHV0aWxpenphIG5vdGF6aW9uaSBtYXRlbWF0aWNoZSBlIG1hdHJpY2kgcGVyIHNlbXBsaWZpY2FyZSBpIGNhbGNvbGkgZSBvdHRlbmVyZSBzb2x1emlvbmkgcGnDuSBlZmZpY2llbnRpIGluIHByb2JsZW1pIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUuCgpDaSBwZXJtZXR0ZSBkaSBwYXNzYXJlIGRhOiAkJCBZID0gXGJldGFfMCArIFxiZXRhXzFYXzEgKyAuLi4gKyBcYmV0YV9uWF9uICsgXGVwc2lsb24gJCQgYSA6ICQkIFkgPSBcYmV0YSBYICsgXGVwc2lsb24gICAkJAoKTGEgc29sdXppb25lIG1hdHJpY2lhbGUgcGVyIHN0aW1hcmUgaSBjb2VmZmljaWVudGkgzrIgw6k6ICQkIFxiZXRhID0gKChYXlQgWCleey0xfSBYXlQgWSkgJCQKCkwnYXBwcm9jY2lvIG1hdHJpY2lhbGUgc2VtcGxpZmljYSBsYSByYXBwcmVzZW50YXppb25lIGUgbGEgcmlzb2x1emlvbmUgZGVpIG1vZGVsbGkgZGkgcmVncmVzc2lvbmUsIHNwZWNpYWxtZW50ZSBxdWFuZG8gc2kgbGF2b3JhIGNvbiBwacO5IHZhcmlhYmlsaSBpbmRpcGVuZGVudGkuCklub2x0cmUsIMOoIHV0aWxlIHBlciBjb21wcmVuZGVyZSBjb21lIGVzZWd1aXJlIGNhbGNvbGkgZGkgcmVncmVzc2lvbmUgaW4gbW9kbyBwacO5IGVmZmljaWVudGUgdXRpbGl6emFuZG8gbWF0cmljaSBlIGFsZ2VicmEgbGluZWFyZSwgc3BlY2lhbG1lbnRlIGluIGNvbnRlc3RpIGRpIGFwcHJlbmRpbWVudG8gYXV0b21hdGljbyBpbiBjdWkgbGUgZGltZW5zaW9uaSBkZWkgZGF0aSBwb3Nzb25vIGVzc2VyZSBlbGV2YXRlLgoKYGBge3J9CiMgQ2FyaWNhIGlsIGRhdGFzZXQgInN3aXNzIiAodW4gZGF0YXNldCBkaSBkYXRpIGRlbW9ncmFmaWNpIHN2aXp6ZXJpKQpkYXRhKHN3aXNzKQoKIyBWaXN1YWxpenphIGxlIHByaW1lIHJpZ2hlIGRlbCBkYXRhc2V0CmhlYWQoc3dpc3MpCgojIENyZWEgbGEgbWF0cmljZSBkZWxsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpClggPC0gYXMubWF0cml4KHN3aXNzWywgYygiRXhhbWluYXRpb24iLCAiRWR1Y2F0aW9uIildKQoKIyBBZ2dpdW5naSB1bmEgY29sb25uYSBkaSAxIHBlciBsJ2ludGVyY2V0dGEKWCA8LSBjYmluZCgxLCBYKQoKIyBDcmVhIGlsIHZldHRvcmUgZGVsbGUgdmFyaWFiaWxpIGRpcGVuZGVudGkKWSA8LSBzd2lzcyRGZXJ0aWxpdHkKCiMgQ2FsY29sYSBpIGNvZWZmaWNpZW50aSBkZWwgbW9kZWxsbyB1dGlsaXp6YW5kbyBsJ2FwcHJvY2NpbyBtYXRyaWNpYWxlCmJldGEgPC0gc29sdmUodChYKSAlKiUgWCkgJSolIHQoWCkgJSolIFkKCiMgVmlzdWFsaXp6YSBpIGNvZWZmaWNpZW50aSBkZWwgbW9kZWxsbwpwcmludChiZXRhKQoKIyBFZmZldHR1YSBwcmV2aXNpb25pIGNvbiBpbCBtb2RlbGxvIG1hdHJpY2lhbGUKcHJlZGljdGlvbnMgPC0gWCAlKiUgYmV0YQoKIyBWYWx1dGEgbGUgcHJlc3RhemlvbmkgZGVsIG1vZGVsbG8KbW9kZWwgPC0gbG0oWSB+IEV4YW1pbmF0aW9uICsgRWR1Y2F0aW9uLCBkYXRhID0gc3dpc3MpICAjIDAgaW5kaWNhIGRpIG5vbiBjYWxjb2xhcmUgbCdpbnRlcmNldHRhCnN1bW1hcnkobW9kZWwpIApgYGAKCi0gICBFc2FtZSAoRXhhbWluYXRpb24pOiBVbiBhdW1lbnRvIG5laSBwdW50ZWdnaSBkaSBlc2FtZSDDqCBhc3NvY2lhdG8gYSB1bmEgZGltaW51emlvbmUgZGVsbGEgZmVydGlsaXTDoCBuZWxsZSByZWdpb25pIHN2aXp6ZXJlLiBRdWVzdG8gc3VnZ2VyaXNjZSBjaGUgdW4gbWlnbGlvcmUgc3RhdG8gZGkgc2FsdXRlIGdlbmVyYWxlLCBtaXN1cmF0byB0cmFtaXRlIGwnZXNhbWUsIMOoIGNvcnJlbGF0byBhIHVuYSBmZXJ0aWxpdMOgIHBpw7kgYmFzc2EuCi0gICBFZHVjYXppb25lIChFZHVjYXRpb24pOiBVbiBhdW1lbnRvIG5lbCBsaXZlbGxvIGRpIGVkdWNhemlvbmUgw6ggY29ycmVsYXRvIGEgdW5hIHJpZHV6aW9uZSBkZWxsYSBmZXJ0aWxpdMOgLiBMZSByZWdpb25pIGNvbiB1biBsaXZlbGxvIGRpIGlzdHJ1emlvbmUgcGnDuSBlbGV2YXRvIHRlbmRvbm8gYWQgYXZlcmUgdW5hIGZlcnRpbGl0w6AgcGnDuSBiYXNzYS4KCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIEludGVycHJldGF6aW9uZSBHZW9tZXRyaWNhCgpMJ2ludGVycHJldGF6aW9uZSBnZW9tZXRyaWNhIGRlbGxhIHJlZ3Jlc3Npb25lIGxpbmVhcmUgw6ggdW4gYXBwcm9jY2lvIGNvbmNldHR1YWxlIGNoZSB1dGlsaXp6YSB1bm8gc3BhemlvIHRyaWRpbWVuc2lvbmFsZSAobyBzdXBlcmlvcmUpIHBlciByYXBwcmVzZW50YXJlIHZpc2l2YW1lbnRlIGlsIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUuCkluIHF1ZXN0byBzcGF6aW8sIG9nbmkgcHVudG8gcmFwcHJlc2VudGEgdW4nb3NzZXJ2YXppb25lIG5lbCBkYXRhc2V0LCBlIHVuIHBpYW5vIChvIGlwZXJwaWFubykgcmFwcHJlc2VudGEgaWwgbW9kZWxsbyBkaSByZWdyZXNzaW9uZS4KTCdvYmlldHRpdm8gw6ggdHJvdmFyZSBpbCBwaWFubyAobyBpcGVycGlhbm8pIGNoZSBtaW5pbWl6emEgbGEgc29tbWEgZGVpIHF1YWRyYXRpIGRlbGxlIGRpc3RhbnplIHZlcnRpY2FsaSB0cmEgaSBwdW50aSBkYXRpIGUgaWwgcGlhbm8gKG8gaXBlcnBpYW5vKS4KUXVlc3RvIGZvcm5pc2NlIHVuYSB2aXN1YWxpenphemlvbmUgaW50dWl0aXZhIGRpIGNvbWUgaSBjb2VmZmljaWVudGkgZGVsIG1vZGVsbG8gdmVuZ29ubyBzdGltYXRpIHBlciBvdHRlbmVyZSBsYSBtaWdsaW9yZSAiYWp1c3RlbWVudCIgYWkgZGF0aSwgbWluaW1penphbmRvIGdsaSBlcnJvcmkgcmVzaWR1aS4KTCdpbnRlcnByZXRhemlvbmUgZ2VvbWV0cmljYSBhaXV0YSBhIGNvbXByZW5kZXJlIGkgcHJpbmNpcGkgZm9uZGFtZW50YWxpIGRlbGxhIHJlZ3Jlc3Npb25lIGxpbmVhcmUgZSBwdcOyIGVzc2VyZSBhcHBsaWNhdGEgYSBwcm9ibGVtaSBwacO5IGNvbXBsZXNzaSBjb24gcGnDuSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpLgoKYGBgYHtyLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHBsb3RseSkKCiMgR2VuZXJhIGRhdGkgY2FzdWFsaQpzZXQuc2VlZCgxMjMpCm4gPC0gNTAKWDEgPC0gcm5vcm0obikKWDIgPC0gcm5vcm0obikKWSA8LSAyICogWDEgKyAzICogWDIgKyBybm9ybShuKQoKIyBDcmVhIHVuIGRhdGFmcmFtZSBjb24gbGUgdmFyaWFiaWxpCmRhdGEgPC0gZGF0YS5mcmFtZShYMSwgWDIsIFkpCgojIEFkYXR0YSBpbCBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUKbW9kZWwgPC0gbG0oWSB+IFgxICsgWDIsIGRhdGEgPSBkYXRhKQpzdW1tYXJ5KG1vZGVsKQoKIyBDcmVhemlvbmUgZGkgdW5hIGdyaWdsaWEgZGkgcHVudGkKeDFfcmFuZ2UgPC0gc2VxKG1pbihYMSksIG1heChYMSksIGxlbmd0aCA9IDIwKQp4Ml9yYW5nZSA8LSBzZXEobWluKFgyKSwgbWF4KFgyKSwgbGVuZ3RoID0gMjApCmdyaWQgPC0gZXhwYW5kLmdyaWQoWDEgPSB4MV9yYW5nZSwgWDIgPSB4Ml9yYW5nZSkKCiMgQ2FsY29sbyBkZWxsZSBwcmV2aXNpb25pIGRlbCBtb2RlbGxvIHN1bGxhIGdyaWdsaWEKZ3JpZCRZX3ByZWQgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IGdyaWQpCgojIENyZWF6aW9uZSBkZWwgcGxvdCAzRCBjb24gcGxvdGx5CiBwbG90X2x5KGRhdGEsIHggPSB+WDEsIHkgPSB+WDIsIHogPSB+WSwgdHlwZSA9ICJzY2F0dGVyM2QiLCBtb2RlID0gIm1hcmtlcnMiLCBtYXJrZXIgPSBsaXN0KHNpemUgPSA1LCBjb2xvciA9ICJibHVlIikpICU+JQogICBhZGRfc3VyZmFjZSgKICAgICB4ID0geDFfcmFuZ2UsCiAgICAgeSA9IHgyX3JhbmdlLAogICAgIHogPSBtYXRyaXgoZ3JpZCRZX3ByZWQsIG5yb3cgPSBsZW5ndGgoeDFfcmFuZ2UpLCBuY29sID0gbGVuZ3RoKHgyX3JhbmdlKSwgYnlyb3cgPSBUUlVFKSwKICAgICBjb2xvcnMgPSAicmVkIiwKICAgICBvcGFjaXR5ID0gMC43CiAgICkgJT4lCiAgIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gIlgxIiksIHlheGlzID0gbGlzdCh0aXRsZSA9ICJYMiIpLCB6YXhpcyA9IGxpc3QodGl0bGUgPSAiWSIpKSkKCmBgYGAKCkwnaW50ZXJwcmV0YXppb25lIGdlb21ldHJpY2EgY2kgY29uc2VudGUgZGkgdmVkZXJlIGNvbWUgaWwgcGlhbm8gZGkgcmVncmVzc2lvbmUgc2kgYWRhdHRhIGFpIGRhdGkgbmVsbG8gc3BhemlvIHRyaWRpbWVuc2lvbmFsZSBlIGNvbWUgaSBjb2VmZmljaWVudGkgc3RpbWF0aSBpbmZsdWVuemFubyBsYSBwb3NpemlvbmUgZSBsJ2luY2xpbmF6aW9uZSBkZWwgcGlhbm8gcmlzcGV0dG8gYWkgZGF0aSBvc3NlcnZhdGkuClF1ZXN0byBmb3JuaXNjZSB1bmEgdmlzdWFsaXp6YXppb25lIGludHVpdGl2YSBkZWxsYSByZWxhemlvbmUgdHJhIGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgZSBkaXBlbmRlbnRpIG5lbCBjb250ZXN0byBkZWxsYSByZWdyZXNzaW9uZSBsaW5lYXJlLgoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIyMgRGlzdHJpYnV6aW9uZSBGICYgQW5vdmEgVGFibGUgeyNkaXN0cmlidXppb25lLWYtYW5vdmEtdGFibGV9CgpMJ0FOT1ZBIHZhbHV0YSBnbG9iYWxtZW50ZSBzZSBhbG1lbm8gdW5hIGRlbGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgaGEgdW4gZWZmZXR0byBzaWduaWZpY2F0aXZvIHN1bGxhIHZhcmlhYmlsZSBkaXBlbmRlbnRlLCBmb3JuaXNjZSB1bmEgc3RhdGlzdGljYSBGIGUgaWwgcmVsYXRpdm8gcC12YWx1ZS4gClVuIHAtdmFsdWUgYmFzc28gc3VnZ2VyaXNjZSBjaGUgYWxtZW5vIHVuYSBkZWxsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpIMOoIHNpZ25pZmljYXRpdmEgbmVsIG1vZGVsbG8uCkwnQU5PVkEgZm9ybmlzY2UgcXVpbmRpIHVuYSB2aXNpb25lIGNvbXBsZXNzaXZhIGRlbGxhIHNpZ25pZmljYXRpdml0w6AgZGVsIG1vZGVsbG8gbmVsIHN1byBjb21wbGVzc28uCgpMJ2FuYWxpc2kgZGVsbGEgdmFyaWFuemEgKEFOT1ZBKSBlIGkgInNpZ25pZi4gY29kZXMiIG5lbCBzdW1tYXJ5IGRlbCBtb2RlbGxvIGZvcm5pc2Nvbm8gaW5mb3JtYXppb25pIHNpbWlsaSwgbWEgc2kgY29uY2VudHJhbm8gc3UgYXNwZXR0aSBkaXZlcnNpIGRlbGwnYW5hbGlzaS4KCkkgInNpZ25pZi4gY29kZXMiIG5lbCBzdW1tYXJ5IGRlbCBtb2RlbGxvIGZvcm5pc2Nvbm8gdW5hIHZhbHV0YXppb25lIHZhcmlhYmlsZSBwZXIgdmFyaWFiaWxlLCBpbmRpY2FuZG8gbGEgc2lnbmlmaWNhdGl2aXTDoCBzdGF0aXN0aWNhIGRpIGNpYXNjdW4gY29lZmZpY2llbnRlLgpVdGlsaXp6YSBhc3RlcmlzY2hpIChcKikgbyBhbHRyaSBzaW1ib2xpIHBlciBpbmRpY2FyZSBpbCBsaXZlbGxvIGRpIHNpZ25pZmljYXRpdml0w6AsIGFkIGVzZW1waW8sICJcKlwqXCoiIHBvdHJlYmJlIGluZGljYXJlIHVuIGxpdmVsbG8gZGkgc2lnbmlmaWNhdGl2aXTDoCBtb2x0byBlbGV2YXRvIChwLXZhbHVlIG1vbHRvIGJhc3NvKSwgbWVudHJlICIgIiAoc3BhemlvKSBwb3RyZWJiZSBpbmRpY2FyZSBub24gc2lnbmlmaWNhdGl2by4KUXVlc3RhIHBhcnRlIGRlbCBzdW1tYXJ5IGZvcm5pc2NlIHVuYSB2aXNpb25lIHBpw7kgZGV0dGFnbGlhdGEgc3VsbGEgc2lnbmlmaWNhdGl2aXTDoCBkaSBjaWFzY3VuYSB2YXJpYWJpbGUgaW5kaXBlbmRlbnRlIHNlcGFyYXRhbWVudGUuCgpMJ0FOT1ZBIHZhbHV0YSBsYSBzaWduaWZpY2F0aXZpdMOgIGRlbCBtb2RlbGxvIG5lbCBzdW8gaW5zaWVtZSwgbWVudHJlIGkgInNpZ25pZi4gY29kZXMiIG5lbCBzdW1tYXJ5IGZvcm5pc2Nvbm8gdW5hIHZpc2lvbmUgZGV0dGFnbGlhdGEgZGVsbGEgc2lnbmlmaWNhdGl2aXTDoCBkaSBjaWFzY3VuYSB2YXJpYWJpbGUgaW5kaXBlbmRlbnRlLgoKKipFc2VtcGlvIDE6KioKCmBgYHtyfQojIENyZWlhbW8gdW4gZGF0YXNldCBmaXR0aXppbwpzZXQuc2VlZCgxMjMpCmRhdGEgPC0gZGF0YS5mcmFtZSgKICBHcnVwcG8gPSByZXAoYygiQSIsICJCIiwgIkMiKSwgZWFjaCA9IDIwKSwKICBQdW50ZWdnaW8gPSBybm9ybSg2MCwgbWVhbiA9IGMoNzAsIDc1LCA4MCksIHNkID0gNSkKKQoKIyBFc2VndWlhbW8gbCdBTk9WQQphbm92YV9yZXN1bHQgPC0gYW92KFB1bnRlZ2dpbyB+IEdydXBwbywgZGF0YSA9IGRhdGEpCgojIFZpc3VhbGl6emlhbW8gbGEgdGFiZWxsYSBBTk9WQQpzdW1tYXJ5KGFub3ZhX3Jlc3VsdCkKYGBgCgpJbiBxdWVzdG8gZXNlbXBpbywgZXNlZ3VpYW1vIHVuJ0FOT1ZBIGEgdW4gZmF0dG9yZSBwZXIgdmFsdXRhcmUgbGUgZGlmZmVyZW56ZSBuZWkgcHVudGVnZ2kgdHJhIGkgZ3J1cHBpIEEsIEIgZSBDLgpJbCByYXBwb3J0byBGIGUgaWwgdmFsb3JlIHAgY2kgcGVybWV0dG9ubyBkaSBkZXRlcm1pbmFyZSBzZSBsZSBkaWZmZXJlbnplIHRyYSBpIGdydXBwaSBzb25vIHN0YXRpc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZlLgoKSSByaXN1bHRhdGkgc3VnZ2VyaXNjb25vIGNoZSBub24gY2kgc29ubyBkaWZmZXJlbnplIHN0YXRpc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZlIHRyYSBpIGdydXBwaSwgb3NzaWEgaWwgdmFyaWFyZSBkZWwgZ3J1cHBvIG5vbiBpbmZsdWVuemEgc2lnbmlmaWNhdGl2YW1lbnRlIGxhIHZhcmlhYmlsZSBkaXBlbmRlbnRlLgpMYSB2YXJpYW56YSB0cmEgaSBncnVwcGkgw6ggbW9sdG8gcGljY29sYSByaXNwZXR0byBhbGxhIHZhcmlhbnphIGFsbCdpbnRlcm5vIGRlaSBncnVwcGksIGUgaWwgdGVzdCBGIG5vbiDDqCBzaWduaWZpY2F0aXZvLgpRdWVzdG8gcHXDsiBpbmRpY2FyZSBjaGUgaSBncnVwcGkgc29ubyBzaW1pbGkgdHJhIGxvcm8gcGVyIHF1YW50byByaWd1YXJkYSBsYSB2YXJpYWJpbGUgaW4gc3R1ZGlvLgoKKipFc2VtcGlvIDI6KioKCmBgYHtyfQojIENyZWlhbW8gdW4gZGF0YXNldCBmaXR0aXppbwpzZXQuc2VlZCgxMjMpCmRhdGEgPC0gZGF0YS5mcmFtZSgKICBHZW5lcmUgPSByZXAoYygiTWFzY2hpbyIsICJGZW1taW5hIiksIGVhY2ggPSA1MCksCiAgVHJhdHRhbWVudG8gPSByZXAoYygiQSIsICJCIiksIHRpbWVzID0gNTApLAogIFB1bnRlZ2dpbyA9IHJub3JtKDEwMCwgbWVhbiA9IGMoNzUsIDgwKSwgc2QgPSA1KQopCgojIEVzZWd1aWFtbyBsJ0FOT1ZBIGEgZHVlIGZhdHRvcmkKYW5vdmFfcmVzdWx0IDwtIGFvdihQdW50ZWdnaW8gfiBHZW5lcmUgKiBUcmF0dGFtZW50bywgZGF0YSA9IGRhdGEpCgojIFZpc3VhbGl6emlhbW8gbGEgdGFiZWxsYSBBTk9WQQpzdW1tYXJ5KGFub3ZhX3Jlc3VsdCkKYGBgCgpJbiBxdWVzdG8gZXNlbXBpbywgZXNlZ3VpYW1vIHVuJ0FOT1ZBIGEgZHVlIGZhdHRvcmkgcGVyIGVzYW1pbmFyZSBsZSBkaWZmZXJlbnplIG5laSBwdW50ZWdnaSBpbiBiYXNlIGFsIGdlbmVyZSBlIGFsIHRyYXR0YW1lbnRvLgoKRGFsbGEgdGFiZWxsYSBkZWxsJ0FOT1ZBIGZvcm5pdGEsIHBvc3NpYW1vIHRyYXJyZSBsZSBzZWd1ZW50aSBjb25jbHVzaW9uaToKCi0gICBJbCBmYXR0b3JlICJUcmF0dGFtZW50byIgaGEgdW4gZm9ydGUgZWZmZXR0byBzdWxsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZSwgY29uIHVuIHZhbG9yZSBkaSBGIGVsZXZhdG8gZSB1biBwLXZhbHVlIG1vbHRvIGJhc3NvLCBpbmRpY2FuZG8gY2hlIGxlIGRpZmZlcmVuemUgdHJhIGkgdHJhdHRhbWVudGkgc29ubyBzdGF0aXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2ZSAoXCpcKlwqKS4KLSAgIElsIGZhdHRvcmUgIkdlbmVyZSIgbm9uIGhhIHVuIGVmZmV0dG8gc2lnbmlmaWNhdGl2byBzdWxsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZSwgY29uIHVuIHZhbG9yZSBkaSBGIGJhc3NvIGUgdW4gcC12YWx1ZSBlbGV2YXRvLgotICAgTCdpbnRlcmF6aW9uZSB0cmEgIkdlbmVyZSIgZSAiVHJhdHRhbWVudG8iIG5vbiBoYSB1biBlZmZldHRvIHNpZ25pZmljYXRpdm8gc3VsbGEgdmFyaWFiaWxlIGRpcGVuZGVudGUsIGNvbiB1biB2YWxvcmUgZGkgRiBlIHVuIHAtdmFsdWUgbm9uIHNpZ25pZmljYXRpdmkuCgpJIHJpc3VsdGF0aSBkZWxsJ0FOT1ZBIHN1Z2dlcmlzY29ubyBjaGUgaWwgIlRyYXR0YW1lbnRvIiDDqCBpbCBwcmluY2lwYWxlIGRyaXZlciBkZWxsZSBkaWZmZXJlbnplIG9zc2VydmF0ZSBuZWxsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZSwgbWVudHJlIGlsICJHZW5lcmUiIGUgbCdpbnRlcmF6aW9uZSB0cmEgIkdlbmVyZSIgZSAiVHJhdHRhbWVudG8iIG5vbiBzZW1icmFubyBhdmVyZSB1biBlZmZldHRvIHNpZ25pZmljYXRpdm8uCgotICAgVW4gdmFsb3JlIEYgbWFnZ2lvcmUgZGkgMSBzdWdnZXJpc2NlIGNoZSBpIHBhcmFtZXRyaSBvIGkgZmF0dG9yaSBzb25vIHNpZ25pZmljYXRpdmksIHBvaWNow6kgbGEgdmFyaWFuemEgc3BpZWdhdGEgw6ggbWFnZ2lvcmUgZGVsbGEgdmFyaWFuemEgbm9uIHNwaWVnYXRhLgotICAgVW4gdmFsb3JlIEYgdmljaW5vIGEgMSBpbmRpY2EgY2hlIGlsIG1vZGVsbG8gbm9uIHNwaWVnYSBpbiBtb2RvIHNpZ25pZmljYXRpdm8gbGEgdmFyaWFiaWxpdMOgIG5laSBkYXRpLgotICAgSWwgdmFsb3JlIHAgYXNzb2NpYXRvIGFsbCdGLXZhbHVlIGZvcm5pc2NlIGxhIHByb2JhYmlsaXTDoCBjaGUgaSByaXN1bHRhdGkgb3NzZXJ2YXRpIHNpYW5vIGRvdnV0aSBhbCBjYXNvLiBVbiB2YWxvcmUgcCBiYXNzbyAoZGkgc29saXRvIGluZmVyaW9yZSBhIDAuMDUpIGluZGljYSB1bmEgc2lnbmlmaWNhdGl2aXTDoCBlbGV2YXRhLCBtZW50cmUgdW4gdmFsb3JlIHAgYWx0byBzdWdnZXJpc2NlIHVuYSBtYW5jYW56YSBkaSBzaWduaWZpY2F0aXZpdMOgLgoKKipTaXN0ZW1hIGRpIGlwb3Rlc2k6KioKCk5lbGwnYW5hbGlzaSBzdGF0aXN0aWNhIGluIGN1aSBzaSBjYWxjb2xhIHVuIHZhbG9yZSBGLCBjaSBzb25vIGR1ZSBpcG90ZXNpIHByaW5jaXBhbGk6IGwnaXBvdGVzaSBudWxsYSAoSDApIGUgbCdpcG90ZXNpIGFsdGVybmF0aXZhIChIMSkuCgpJcG90ZXNpIE51bGxhIChIMCk6IEwnaXBvdGVzaSBudWxsYSBhZmZlcm1hIGNoZSBub24gY2kgc29ubyBkaWZmZXJlbnplIHNpZ25pZmljYXRpdmUgdHJhIGkgZ3J1cHBpIG8gaSBmYXR0b3JpIGNvbnNpZGVyYXRpLgpJbiBhbHRyZSBwYXJvbGUsIGwnaXBvdGVzaSBudWxsYSBzb3N0aWVuZSBjaGUgaSBwYXJhbWV0cmkgZGVsIG1vZGVsbG8gbyBpIGZhdHRvcmkgbm9uIGhhbm5vIHVuIGVmZmV0dG8gc2lnbmlmaWNhdGl2byBzdWwgcmlzdWx0YXRvIG8gY2hlIGxlIGRpZmZlcmVuemUgb3NzZXJ2YXRlIHNvbm8gY2FzdWFsaS4KCklwb3Rlc2kgQWx0ZXJuYXRpdmEgKEgxIG8gSEEpOiBMJ2lwb3Rlc2kgYWx0ZXJuYXRpdmEgw6ggaWwgY29udHJhcmlvIGRlbGwnaXBvdGVzaSBudWxsYS4KU29zdGllbmUgY2hlIGNpIHNvbm8gZGlmZmVyZW56ZSBzaWduaWZpY2F0aXZlIHRyYSBpIGdydXBwaSBvIGkgZmF0dG9yaSBjb25zaWRlcmF0aSwgZSBjaGUgbGUgZGlmZmVyZW56ZSBvc3NlcnZhdGUgbm9uIHNvbm8gY2FzdWFsaSwgbWEgc29ubyBkb3Z1dGUgYSB1biBlZmZldHRvIHNpZ25pZmljYXRpdm8gZGVpIHBhcmFtZXRyaSBkZWwgbW9kZWxsbyBvIGRlaSBmYXR0b3JpLgoKQ29udGludWlhbW8gbCdlc2VtcGlvIGRpIHByaW1hOgoKYGBge3J9Cm1vZGVsIDwtIGxtKFB1bnRlZ2dpbyB+IEdlbmVyZSAqIFRyYXR0YW1lbnRvLCBkYXRhID0gZGF0YSkKc3VtbWFyeShtb2RlbCkKCiMgRXN0cmFpYW1vIGlsIHZhbG9yZSBwCnBfdmFsdWUgPC0gYW5vdmFfc3VtbWFyeVtbMV1dW1siUHIoPkYpIl1dWzNdICAjIFVzaWFtbyBbM10gcGVyIGVzdHJhcnJlIGlsIHZhbG9yZSByZWxhdGl2byBhbGwnaW50ZXJhemlvbmUKCgojIFNjZWdsaWFtbyB1biBsaXZlbGxvIGRpIHNpZ25pZmljYXRpdml0w6AgKGFscGhhKQphbHBoYSA8LSAwLjA1CgojIFZhbHV0aWFtbyBzZSByaWZpdXRhcmUgbCdpcG90ZXNpIG51bGxhCmlmIChwX3ZhbHVlIDwgYWxwaGEpIHsKICBjYXQoIlJpZml1dGlhbW8gbCdpcG90ZXNpIG51bGxhLiBDaSBzb25vIGRpZmZlcmVuemUgc2lnbmlmaWNhdGl2ZSB0cmEgaSBncnVwcGkuXG4iKQp9IGVsc2UgewogIGNhdCgiTm9uIHJpZml1dGlhbW8gbCdpcG90ZXNpIG51bGxhLiBOb24gY2kgc29ubyBkaWZmZXJlbnplIHNpZ25pZmljYXRpdmUgdHJhIGkgZ3J1cHBpLlxuIikKfQpgYGAKCkxhIEYtc3RhdGlzdGljIG5lbCBzdW1tYXJ5IGRpIHVuIG1vZGVsbG8gbGluZWFyZSAobG0pIHJhcHByZXNlbnRhIGxhIHN0YXRpc3RpY2EgZGVsIHRlc3QgRiBwZXIgbCdpbnRlcm8gbW9kZWxsby4gUXVlc3RvIHRlc3QgdmVyaWZpY2Egc2UgYyfDqCBhbG1lbm8gdW5hIHZhcmlhYmlsZSBpbmRpcGVuZGVudGUgbmVsIG1vZGVsbG8gY2hlIMOoIHNpZ25pZmljYXRpdmFtZW50ZSBhc3NvY2lhdGEgYWxsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZS4gSW4gYWx0cmUgcGFyb2xlLCB2YWx1dGEgbCdpcG90ZXNpIG51bGxhIGNoZSB0dXR0aSBpIGNvZWZmaWNpZW50aSBkZWxsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpIG5lbCBtb2RlbGxvIHNpYW5vIHVndWFsaSBhIHplcm8gKGNpb8OoIGNoZSBub24gY2kgc2lhbm8gZWZmZXR0aSkuCgpJbiBicmV2ZSBsYSBGLXN0YXRpc3RpYyBzdWdnZXJpc2NlIGNoZSBhbG1lbm8gdW5hIGRlbGxlIGludGVyYXppb25pIHRyYSAiR2VuZXJlIiBlICJUcmF0dGFtZW50byIgbyBhbG1lbm8gdW5hIGRlbGxlIHByaW5jaXBhbGkgZWZmZXR0aSDDqCBzaWduaWZpY2F0aXZhIG5lbCBtb2RlbGxvLgoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIyMgTW9kZWxsaSBOaWRpZmljYXRpCgpOZWkgbW9kZWxsaSBzdGF0aXN0aWNpLCB1biAibmVzdGVkIG1vZGVsIiBzaSB2ZXJpZmljYSBxdWFuZG8gdW4gbW9kZWxsbyBwacO5IGNvbXBsZXNzbyBvIGdlbmVyYWxlIHB1w7IgZXNzZXJlIHN1ZGRpdmlzbyBvIHNlbXBsaWZpY2F0byBpbiB1biBtb2RlbGxvIHBpw7kgc2VtcGxpY2UgbyBzcGVjaWZpY28uCklsIG1vZGVsbG8gcGnDuSBzZW1wbGljZSDDqCBjb25zaWRlcmF0byAibmlkaWZpY2F0byIgYWxsJ2ludGVybm8gZGVsIG1vZGVsbG8gcGnDuSBjb21wbGVzc28sIHBvaWNow6kgY29udGllbmUgdW4gc290dG9pbnNpZW1lIGRpIHBhcmFtZXRyaSBvIHZpbmNvbGkgZGVsIG1vZGVsbG8gcGnDuSBnZW5lcmFsZS4KCk5lbCBjb250ZXN0byBkZWxsYSByZWdyZXNzaW9uZSwgaSBtb2RlbGxpIG5pZGlmaWNhdGkgc29ubyBzcGVzc28gdXRpbGl6emF0aSBwZXIgdGVzdGFyZSBsJ2FnZ2l1bnRhIGRpIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgYWwgbW9kZWxsbyBhbCBmaW5lIGRpIHZhbHV0YXJlIHNlIGxlIHZhcmlhYmlsaSBhZ2dpdW50aXZlIG1pZ2xpb3Jhbm8gc2lnbmlmaWNhdGl2YW1lbnRlIGxhIGNhcGFjaXTDoCBkaSBwcmV2aXNpb25lIG8gc3BpZWdhemlvbmUgZGVsIG1vZGVsbG8uCkkgbW9kZWxsaSBuaWRpZmljYXRpIHNvbm8gYW5jaGUgdXRpbGl6emF0aSBpbiBjb250ZXN0aSBjb21lIGwnYW5hbGlzaSBkZWxsYSB2YXJpYW56YSAoQU5PVkEpLCBsJ2FuYWxpc2kgZGVsbGEgZGV2aWFuemEgbmVpIG1vZGVsbGkgbGluZWFyaSBnZW5lcmFsaXp6YXRpIChjaGUgdmVkcmVtbyBwacO5IGF2YW50aSkgZSBhbHRyZSBwcm9jZWR1cmUgc3RhdGlzdGljaGUuCgpFc2VtcGlvIGRpIE1vZGVsbGkgZGkgUmVncmVzc2lvbmUgTmlkaWZpY2F0aToKClN1cHBvbmlhbW8gZGkgdm9sZXIgY3JlYXJlIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgcGVyIHByZXZlZGVyZSBpbCByZWRkaXRvIGRpIHVuYSBwZXJzb25hIGJhc2FuZG9jaSBzdSBxdWF0dHJvIHZhcmlhYmlsaSBpbmRpcGVuZGVudGk6IGV0w6AsIGlzdHJ1emlvbmUsIGVzcGVyaWVuemEgbGF2b3JhdGl2YSBlIGdlbmVyZS4KSWwgbW9kZWxsbyBjb21wbGV0byBwb3RyZWJiZSBlc3NlcmU6CgoqKk1vZGVsbG8gQ29tcGxldG8qKgoKJCQgUmVkZGl0byA9IFxiZXRhXzAgKyBcYmV0YV8xIFxjZG90IEV0w6AgKyBcYmV0YV8yIFxjZG90IElzdHJ1emlvbmUgKyBcYmV0YV8zIFxjZG90IEVzcGVyaWVuemEgKyBcYmV0YV80IFxjZG90IEdlbmVyZSAkJCBUdXR0YXZpYSwgcG90cmVtbW8gZXNzZXJlIGludGVyZXNzYXRpIGEgdmFsdXRhcmUgc2UgbCdhZ2dpdW50YSBkZWxsYSB2YXJpYWJpbGUgImdlbmVyZSIgbWlnbGlvcmEgc2lnbmlmaWNhdGl2YW1lbnRlIGxhIGNhcGFjaXTDoCBwcmVkaXR0aXZhIGRlbCBtb2RlbGxvLgpJbiB0YWwgY2FzbywgaWwgbW9kZWxsbyBzZW56YSAiZ2VuZXJlIiDDqCBuaWRpZmljYXRvIGFsbCdpbnRlcm5vIGRlbCBtb2RlbGxvIGNvbXBsZXRvOgoKKipNb2RlbGxvIE5pZGlmaWNhdG8qKgoKJCQgUmVkZGl0bycgPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBFdMOgICsgXGJldGFfMiBcY2RvdCBJc3RydXppb25lICsgXGJldGFfMyBcY2RvdCBFc3BlcmllbnphICQkCgpJbiBxdWVzdG8gZXNlbXBpbywgaWwgTW9kZWxsbyAxIMOoIGlsIG1vZGVsbG8gY29tcGxldG8gZSBpbCBNb2RlbGxvIDIgw6ggaWwgbW9kZWxsbyBuaWRpZmljYXRvIHNlbnphIGlsIHBhcmFtZXRybyBwZXIgImdlbmVyZSIuClZhbHV0aWFtbyB0cmFtaXRlIHVuIEFOT1ZBIHF1YWxlIGRlaSBkdWUgbW9kZWxsaSBzaWEgY29uc2lkZXJhdG8gcGnDuSBzaWduaWZpY2F0aXZvLgoKCmBgYHtyfQojIENyZWlhbW8gZGF0aSBmaXR0aXppCnNldC5zZWVkKDEyMykKbiA8LSAxMDAKZXRhIDwtIHJub3JtKG4sIG1lYW4gPSAzNSwgc2QgPSA1KQppc3RydXppb25lIDwtIHJub3JtKG4sIG1lYW4gPSAxMiwgc2QgPSAyKQplc3BlcmllbnphIDwtIHJub3JtKG4sIG1lYW4gPSAxMCwgc2QgPSAzKQpnZW5lcmUgPC0gc2FtcGxlKGMoIk1hc2NoaW8iLCAiRmVtbWluYSIpLCBuLCByZXBsYWNlID0gVFJVRSkKcmVkZGl0byA8LSAyMCArIDIgKiBldGEgKyAzICogaXN0cnV6aW9uZSArIDUgKiBlc3BlcmllbnphICsgaWZlbHNlKGdlbmVyZSA9PSAiTWFzY2hpbyIsIDQsIDApICsgcm5vcm0obiwgbWVhbiA9IDAsIHNkID0gNSkKCiMgQ3JlaWFtbyB1biBkYXRhZnJhbWUgY29uIGkgZGF0aQpkYXRhIDwtIGRhdGEuZnJhbWUoZXRhLCBpc3RydXppb25lLCBlc3BlcmllbnphLCBnZW5lcmUsIHJlZGRpdG8pCgojIE1vZGVsbG8gY29tcGxldG8KbW9kZWxsb19jb21wbGV0byA8LSBsbShyZWRkaXRvIH4gZXRhICsgaXN0cnV6aW9uZSArIGVzcGVyaWVuemEgKyBnZW5lcmUsIGRhdGEgPSBkYXRhKQoKIyBNb2RlbGxvIG5pZGlmaWNhdG8gc2VuemEgImdlbmVyZSIKbW9kZWxsb19uaWRpZmljYXRvIDwtIGxtKHJlZGRpdG8gfiBldGEgKyBpc3RydXppb25lICsgZXNwZXJpZW56YSwgZGF0YSA9IGRhdGEpCgojIFRlc3QgRiBwZXIgY29uZnJvbnRhcmUgaSBtb2RlbGxpCmFub3ZhX3Jlc3VsdCA8LSBhbm92YShtb2RlbGxvX25pZGlmaWNhdG8sIG1vZGVsbG9fY29tcGxldG8pCgojIFZpc3VhbGl6emlhbW8gbGEgdGFiZWxsYSBBTk9WQQpwcmludChhbm92YV9yZXN1bHQpCgojIFNjZWdsaWFtbyB1biBsaXZlbGxvIGRpIHNpZ25pZmljYXRpdml0w6AgKGFscGhhKQphbHBoYSA8LSAwLjA1CgojIFZhbHV0aWFtbyBzZSByaWZpdXRhcmUgbCdpcG90ZXNpIG51bGxhCmlmIChhbm92YV9yZXN1bHRbMiwgIlByKD5GKSJdIDwgYWxwaGEpIHsKICBjYXQoIkxhIHJpbW96aW9uZSBkaSAnZ2VuZXJlJyBub24gbWlnbGlvcmEgc2lnbmlmaWNhdGl2YW1lbnRlIGlsIG1vZGVsbG8uXG4iKQp9IGVsc2UgewogIGNhdCgiTGEgcmltb3ppb25lIGRpICdnZW5lcmUnIG1pZ2xpb3JhIHNpZ25pZmljYXRpdmFtZW50ZSBpbCBtb2RlbGxvLlxuIikKfQoKIyBSIFNxdWFyZWQgZGVpIGR1ZSBtb2RlbGxpCnByaW50KCJNb2RlbGxvIGNvbXBsZXRvICIpIApzdW1tYXJ5KG1vZGVsbG9fY29tcGxldG8pJHIuc3F1YXJlZApwcmludCgiTW9kZWxsbyBhbm5pZGF0byAiKQpzdW1tYXJ5KG1vZGVsbG9fbmlkaWZpY2F0bykkci5zcXVhcmVkCmBgYAoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIyMgU2VsZXppb25lIGRlbGxlIHZhcmlhYmlsaQoKTGEgInZhcmlhYmxlIHNlbGVjdGlvbiIgw6ggdW4gcHJvY2Vzc28gYXR0cmF2ZXJzbyBpbCBxdWFsZSBzaSBzY2VsZ29ubyBsZSB2YXJpYWJpbGkgcGnDuSByaWxldmFudGkgZGEgaW5jbHVkZXJlIGluIHVuIG1vZGVsbG8gc3RhdGlzdGljby4KUXVlc3RvIHByb2Nlc3NvIMOoIHV0aWxlIHBlciBzZW1wbGlmaWNhcmUgaSBtb2RlbGxpLCBtaWdsaW9yYXJlIGxhIGNhcGFjaXTDoCBwcmVkaXR0aXZhIGUgbGEgY29tcHJlbnNpb25lIGRlaSBkYXRpLCByaWR1cnJlIGwnb3ZlcmZpdHRpbmcgZSBhdW1lbnRhcmUgbCdlZmZpY2llbnphIGNvbXB1dGF6aW9uYWxlLgoKVW4gbWV0b2RvIGNvbXVuZSBwZXIgbGEgc2VsZXppb25lIGRlbGxlIHZhcmlhYmlsaSBpbiBSIGNvaW52b2xnZSBsJ3V0aWxpenpvIGRlbGwnSW5mb3JtYXRpb24gQ3JpdGVyaW9uIChDcml0ZXJpbyBkJ0luZm9ybWF6aW9uZSkgZGkgQWthaWtlIChBSUMpIGluc2llbWUgYWxsYSBmdW56aW9uZSBzdGVwKCkuCgoqKkFJQyAoQWthaWtlJ3MgSW5mb3JtYXRpb24gQ3JpdGVyaW9uKToqKgoKSWwgQ3JpdGVyaW8gZCdJbmZvcm1hemlvbmUgZGkgQWthaWtlIChBSUMpIMOoIHVuYSBtZXRyaWNhIGNoZSBtaXN1cmEgbGEgcXVhbGl0w6AgZGkgdW4gbW9kZWxsbyBzdGF0aXN0aWNvLgpMJ29iaWV0dGl2byBkZWxsJ0FJQyDDqCB0cm92YXJlIGlsIG1pZ2xpb3IgY29tcHJvbWVzc28gdHJhIGxhIGJvbnTDoCBkaSBhZGF0dGFtZW50byBkZWwgbW9kZWxsbyBhaSBkYXRpIGUgbGEgc3VhIGNvbXBsZXNzaXTDoC4KTCdBSUMgdGllbmUgY29udG8gZGVsbGEgZnVuemlvbmUgZGkgdmVyb3NpbWlnbGlhbnphIGRlbCBtb2RlbGxvIGUgcGVuYWxpenphIGkgbW9kZWxsaSBjb24gdW4gbnVtZXJvIG1hZ2dpb3JlIGRpIHBhcmFtZXRyaS4KTCdBSUMgw6ggZGVmaW5pdG8gY29tZToKCiQkIEFJQyA9IC0ybG9nTGlrZWxpaG9vZCArIDJrICQkCgpEb3ZlOgoKLSAgICJsb2ctbGlrZWxpaG9vZCIgw6ggaWwgbG9nYXJpdG1vIGRlbGxhIGZ1bnppb25lIGRpIHZlcm9zaW1pZ2xpYW56YSBkZWwgbW9kZWxsby4KLSAgICJrIiDDqCBpbCBudW1lcm8gZGkgcGFyYW1ldHJpIHN0aW1hdGkgbmVsIG1vZGVsbG8uIFVuIHZhbG9yZSBBSUMgcGnDuSBiYXNzbyBpbmRpY2EgdW4gbW9kZWxsbyBtaWdsaW9yZSwgaW4gcXVhbnRvIGluZGljYSB1biBtaWdsaW9yZSBhZGF0dGFtZW50byBhaSBkYXRpIGNvbiBtZW5vIGNvbXBsZXNzaXTDoC4KCioqRnVuemlvbmUgc3RlcCgpOioqCgpMYSBmdW56aW9uZSBzdGVwKCkgaW4gUiDDqCB1dGlsaXp6YXRhIHBlciBlZmZldHR1YXJlIGxhIHNlbGV6aW9uZSBkZWxsZSB2YXJpYWJpbGkgYmFzYXRhIHN1IGNyaXRlcmkgY29tZSBsJ0FJQy4KQ29uc2VudGUgZGkgY29uZnJvbnRhcmUgZSBzZWxlemlvbmFyZSBpIG1vZGVsbGkgaW4gbW9kbyBhdXRvbWF0aWNvIGFnZ2l1bmdlbmRvIG8gcmltdW92ZW5kbyB2YXJpYWJpbGkgZGFsIG1vZGVsbG8sIGZpbm8gYSB0cm92YXJlIGlsIG1vZGVsbG8gY29uIGwnQUlDIHBpw7kgYmFzc28uCkxhIHNpbnRhc3NpIGRpIGJhc2UgZGVsbGEgZnVuemlvbmUgc3RlcCgpIMOoIGxhIHNlZ3VlbnRlOgoKYGBge3J9CiNzdGVwKG1vZGVsbG9faW5pemlhbGUsIGRpcmVjdGlvbiA9ICJib3RoIiwgc2NvcGUgPSBsaXN0KGxvd2VyID0gbW9kZWxsb19taW5pbW8sIHVwcGVyID0gbW9kZWxsb19tYXNzaW1vKSkKYGBgCgotICAgbW9kZWxsb19pbml6aWFsZSDDqCBpbCBtb2RlbGxvIGRpIHBhcnRlbnphIGNoZSBkZXNpZGVyaSBzZW1wbGlmaWNhcmUgbyBtaWdsaW9yYXJlLgotICAgZGlyZWN0aW9uIHB1w7IgZXNzZXJlICJmb3J3YXJkIiwgImJhY2t3YXJkIiwgbyAiYm90aCIgZSBzcGVjaWZpY2Egc2UgYWdnaXVuZ2VyZSwgcmltdW92ZXJlIG8gZW50cmFtYmkgaSB0aXBpIGRpIHZhcmlhYmlsaSBkdXJhbnRlIGxhIHNlbGV6aW9uZS4KLSAgIHNjb3BlIHNwZWNpZmljYSBsJ2ludGVydmFsbG8gZGVpIG1vZGVsbGkgZGEgY29uc2lkZXJhcmUgZHVyYW50ZSBsYSBzZWxlemlvbmUuIElsIC0gIm1vZGVsbG9fbWluaW1vIiByYXBwcmVzZW50YSBpbCBtb2RlbGxvIHBpw7kgc2VtcGxpY2UgcG9zc2liaWxlIChhZCBlc2VtcGlvLCB1biBtb2RlbGxvIGNvbiBzb2xvIGwnaW50ZXJjZXR0YSksIG1lbnRyZSBpbCAibW9kZWxsb19tYXNzaW1vIiByYXBwcmVzZW50YSBpbCBtb2RlbGxvIHBpw7kgY29tcGxlc3NvIChpbCBtb2RlbGxvIGNvbXBsZXRvIGNvbiB0dXR0ZSBsZSB2YXJpYWJpbGkpLgoKYGBge3J9CiMgQ2FyaWNhIGlsIGRhdGFzZXQgZGkgZXNlbXBpbwpkYXRhKG10Y2FycykKCiMgQ3JlYSB1biBtb2RlbGxvIGxpbmVhcmUgaW5pemlhbGUKYWxsIDwtIGxtKG1wZyB+IC4sIGRhdGEgPSBtdGNhcnMpCgojIEVzZWd1aSBsYSBzZWxlemlvbmUgZGVsbGUgdmFyaWFiaWxpIGJhc2F0YSBzdSBBSUMKYmVzdCA8LSBzdGVwKGFsbCwgZGlyZWN0aW9uID0gImJhY2t3YXJkIikKYGBgCgpJbiBxdWVzdG8gZXNlbXBpbywgcGFydGlhbW8gZGEgdW4gbW9kZWxsbyBsaW5lYXJlIGNvbXBsZXRvIGNoZSB1dGlsaXp6YSB0dXR0ZSBsZSB2YXJpYWJpbGkgZGkgbXRjYXJzLCBlIHBvaSB1dGlsaXp6aWFtbyBzdGVwKCkgcGVyIGVzZWd1aXJlIGxhIHNlbGV6aW9uZSBkZWxsZSB2YXJpYWJpbGkgYmFzYXRhIHN1IEFJQy4KQWxsYSBmaW5lLCBvdHRlbmlhbW8gaWwgbW9kZWxsbyBjb24gbCdBSUMgcGnDuSBiYXNzbywgY2hlIGRvdnJlYmJlIGVzc2VyZSB1bmEgdmVyc2lvbmUgc2VtcGxpZmljYXRhIGRlbCBtb2RlbGxvIGluaXppYWxlIGNvbiBzb2xvIGxlIHZhcmlhYmlsaSBwacO5IHJpbGV2YW50aS4KCkxhICJ2YXJpYWJsZSBzZWxlY3Rpb24iIHV0aWxpenphbmRvIEFJQyBlIHN0ZXAoKSDDqCB1biBwb3RlbnRlIHN0cnVtZW50byBwZXIgbWlnbGlvcmFyZSBsYSBxdWFsaXTDoCBlIGwnaW50ZXJwcmV0YWJpbGl0w6AgZGVpIG1vZGVsbGkgc3RhdGlzdGljaSwgaW4gcGFydGljb2xhcmUgcXVhbmRvIHNpIGhhbm5vIG1vbHRpIHBvdGVuemlhbGkgcHJlZGl0dG9yaS4KCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIFByZWRpemlvbmkgQ2F0ZWdvcmljaGUKCk5lbGwnYW5hbGlzaSBzdGF0aXN0aWNhLCBpICJjYXRlZ29yaWNhbCBwcmVkaWN0b3JzIiBzb25vIHZhcmlhYmlsaSBjaGUgcmFwcHJlc2VudGFubyBjYXRlZ29yaWUgbyBncnVwcGkgZGlzdGludGkgYW56aWNow6kgdmFsb3JpIG51bWVyaWNpLgpRdWVzdGUgdmFyaWFiaWxpIHNvbm8gYW5jaGUgY29ub3NjaXV0ZSBjb21lIHZhcmlhYmlsaSBxdWFsaXRhdGl2ZSBvIGZhdHRvcmkuCkFkIGVzZW1waW8sIGlsIGdlbmVyZSAobWFzY2hpby9mZW1taW5hKSwgaWwgbGl2ZWxsbyBkaSBpc3RydXppb25lIChzY3VvbGEgZWxlbWVudGFyZSwgc2N1b2xhIG1lZGlhLCBsYXVyZWEpLCBvIGlsIHRpcG8gZGkgcHJvZG90dG8gKEEsIEIsIEMpIHNvbm8gZXNlbXBpIGRpIHByZWRpdHRvcmkgY2F0ZWdvcmljaS4KUXVhbmRvIHNpIHV0aWxpenphbm8gcHJlZGl0dG9yaSBjYXRlZ29yaWNpIGluIHVuIG1vZGVsbG8gc3RhdGlzdGljbywgw6ggaW1wb3J0YW50ZSBjb25zaWRlcmFyZSBjb21lIGdlc3RpcmUgZSBpbnRlcnByZXRhcmUgcXVlc3RpIGRhdGkuCgpVbmEgY29uc2lkZXJhemlvbmUgZm9uZGFtZW50YWxlIMOoIGNvbWUgcmFwcHJlc2VudGFyZSBsZSB2YXJpYWJpbGkgY2F0ZWdvcmljaGUgbmVsIG1vZGVsbG8uClNvbGl0YW1lbnRlLCB2ZW5nb25vIHV0aWxpenphdGUgZGVsbGUgdmFyaWFiaWxpIGR1bW15ICh2YXJpYWJpbGkgaW5kaWNhdHJpY2kpIHBlciByYXBwcmVzZW50YXJlIGxlIGNhdGVnb3JpZS4KQWQgZXNlbXBpbywgbmVsIGNhc28gZGVsIGdlbmVyZSAobWFzY2hpby9mZW1taW5hKSwgcG90cmViYmVybyBlc3NlcmUgY3JlYXRlIGR1ZSB2YXJpYWJpbGkgZHVtbXksIHVuYSBwZXIgaWwgbWFzY2hpbyBlIHVuYSBwZXIgbGEgZmVtbWluYS4KUXVlc3RlIHZhcmlhYmlsaSBkdW1teSBwcmVuZG9ubyBpbCB2YWxvcmUgMSBvIDAgYSBzZWNvbmRhIGRlbGwnYXBwYXJ0ZW5lbnphIGFsbGEgY2F0ZWdvcmlhLgpRdWVzdG8gYXBwcm9jY2lvIGNvbnNlbnRlIGFsIG1vZGVsbG8gZGkgY2F0dHVyYXJlIGwnZWZmZXR0byBkZWxsYSBjYXRlZ29yaWEgc3VsbGEgdmFyaWFiaWxlIGRpcGVuZGVudGUuCgpPbHRyZSBhbGxhIHJhcHByZXNlbnRhemlvbmUgZGVsbGUgdmFyaWFiaWxpIGNhdGVnb3JpY2hlLCDDqCBpbXBvcnRhbnRlIGNvbnNpZGVyYXJlIGxlIGludGVyYXppb25pIHRyYSBpIHByZWRpdHRvcmkuCkxlIGludGVyYXppb25pIHNpIHZlcmlmaWNhbm8gcXVhbmRvIGwnZWZmZXR0byBkaSB1bmEgdmFyaWFiaWxlIGNhdGVnb3JpY2Egc3VsIHJpc3VsdGF0byBkaXBlbmRlIGRhIHVuJ2FsdHJhIHZhcmlhYmlsZS4KQWQgZXNlbXBpbywgbCdlZmZldHRvIGRlbCBsaXZlbGxvIGRpIGlzdHJ1emlvbmUgc3VsIHJlZGRpdG8gcG90cmViYmUgdmFyaWFyZSBpbiBiYXNlIGFsIGdlbmVyZS4KSW4gcXVlc3RvIGNhc28sIGMnw6ggdW4naW50ZXJhemlvbmUgdHJhIGlsIGxpdmVsbG8gZGkgaXN0cnV6aW9uZSBlIGlsIGdlbmVyZS4KClBlciBlc2FtaW5hcmUgbGUgaW50ZXJhemlvbmkgdHJhIHByZWRpdHRvcmkgY2F0ZWdvcmljaSwgw6ggcG9zc2liaWxlIHV0aWxpenphcmUgbCdhbmFsaXNpIGRlbGxhIHZhcmlhbnphIChBTk9WQSkgbyBpIG1vZGVsbGkgbGluZWFyaSBnZW5lcmFsaXp6YXRpIChjaGUgdmVkcmVtbyBwacO5IGF2YW50aSkuCkxlIGludGVyYXppb25pIHBvc3Nvbm8gZm9ybmlyZSBpbmZvcm1hemlvbmkgcHJlemlvc2Ugc3VsbCdpbmZsdWVuemEgY29tYmluYXRhIGRlbGxlIHZhcmlhYmlsaSBjYXRlZ29yaWNoZSBzdWwgcmlzdWx0YXRvLgoKYGBge3J9CiMgQ3JlaWFtbyBkYXRpIGZpdHRpemkKc2V0LnNlZWQoMTIzKQpuIDwtIDEwMApnZW5lcmUgPC0gc2FtcGxlKGMoIk1hc2NoaW8iLCAiRmVtbWluYSIpLCBuLCByZXBsYWNlID0gVFJVRSkKaXN0cnV6aW9uZSA8LSByZXAoYygiRWxlbWVudGFyZSIsICJNZWRpYSIsICJMYXVyZWEiKSwgbGVuZ3RoLm91dCA9IG4gKQpyZWRkaXRvIDwtIDMwICsgaWZlbHNlKGdlbmVyZSA9PSAiTWFzY2hpbyIsIDUsIDApICsgaWZlbHNlKGlzdHJ1emlvbmUgPT0gIkxhdXJlYSIsIDEwLCAwKSArIHJub3JtKG4sIG1lYW4gPSAwLCBzZCA9IDUpCgojIENyZWlhbW8gdW4gZGF0YWZyYW1lIGNvbiBpIGRhdGkKZGF0YSA8LSBkYXRhLmZyYW1lKGdlbmVyZSwgaXN0cnV6aW9uZSwgcmVkZGl0bykKCiMgTW9kZWxsbyBjb24gaW50ZXJhemlvbmUgdHJhIGdlbmVyZSBlIGlzdHJ1emlvbmUKbW9kZWxsbyA8LSBsbShyZWRkaXRvIH4gZ2VuZXJlICogaXN0cnV6aW9uZSwgZGF0YSA9IGRhdGEpCgojIFZpc3VhbGl6emlhbW8gaSByaXN1bHRhdGkKc3VtbWFyeShtb2RlbGxvKQphbm92YShtb2RlbGxvLCB0ZXN0ID0gImNoaSIpCgojIEdyYWZpY28gcmVkZGl0byBwZXIgc29saSBtYXNjaGkgZSBzb2xlIGZlbW1pbmUKZ2dwbG90KGRhdGEgPSBkYXRhLCBhZXMoeCA9IGlzdHJ1emlvbmUsIHkgPSByZWRkaXRvLCBmaWxsID0gZ2VuZXJlKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHggPSAiSXN0cnV6aW9uZSIsIHkgPSAiUmVkZGl0byIpCmBgYAoKSW4gcXVlc3RvIGVzZW1waW8sIHN0aWFtbyBjcmVhbmRvIGRhdGkgZml0dGl6aSBjb24gZHVlIHByZWRpdHRvcmkgY2F0ZWdvcmljaTogImdlbmVyZSIgZSAiaXN0cnV6aW9uZSIuCklsIG1vZGVsbG8gbGluZWFyZSBpbmNsdWRlIHVuJ2ludGVyYXppb25lIHRyYSBxdWVzdGkgZHVlIHByZWRpdHRvcmkuCkxhIHRhYmVsbGEgZGVpIHJpc3VsdGF0aSBzdW1tYXJ5KG1vZGVsbG8pIG1vc3RyYSBjb21lIGkgcHJlZGl0dG9yaSBjYXRlZ29yaWNpIGUgbCdpbnRlcmF6aW9uZSBpbmZsdWVuemFubyBpbCByZWRkaXRvLgoKUG9zc2lhbW8gY29uY2x1ZGVyZSBjaGUgaWwgZ2VuZXJlIGUgaWwgbGl2ZWxsbyBkaSBpc3RydXppb25lIGhhbm5vIHVuIGVmZmV0dG8gc2lnbmlmaWNhdGl2byBzdWwgcmVkZGl0bywgbWVudHJlIGxlIGludGVyYXppb25pIHRyYSBnZW5lcmUgZSBpc3RydXppb25lIG5vbiBzb25vIHNpZ25pZmljYXRpdmUgaW4gcXVlc3RvIG1vZGVsbG8uCklsIG1vZGVsbG8gbmVsIHN1byBjb21wbGVzc28gw6ggc2lnbmlmaWNhdGl2byBlIGluIGdyYWRvIGRpIHNwaWVnYXJlIHVuYSBwYXJ0ZSBkZWxsYSB2YXJpYXppb25lIG5lbCByZWRkaXRvLgoKKipGYXR0b3JpIGNvbiBwacO5IGRpIGR1ZSBjYXRlZ29yaWU6KioKClF1YW5kbyBzaSBhZmZyb250YW5vIGZhdHRvcmkgY29uIHBpw7kgZGkgZHVlIGxpdmVsbGkgKGNhdGVnb3JpZSksIMOoIG5lY2Vzc2FyaW8gY29uc2lkZXJhcmUgY29tZSBnZXN0aXJlIHF1ZXN0ZSB2YXJpYWJpbGkgbmVsIG1vZGVsbG8uCkluIGdlbmVyYWxlLCB1biBmYXR0b3JlIGNvbiBrIGxpdmVsbGkgcmljaGllZGUgbGEgY3JlYXppb25lIGRpIGstMSB2YXJpYWJpbGkgZHVtbXkgcGVyIGV2aXRhcmUgbGEgImR1bW15IHZhcmlhYmxlIHRyYXAiLgpRdWVzdG8gc2kgdmVyaWZpY2EgcXVhbmRvIGxlIHZhcmlhYmlsaSBkdW1teSBzb25vIGxpbmVhcm1lbnRlIGRpcGVuZGVudGkgZSBwb3Nzb25vIHBvcnRhcmUgYSBwcm9ibGVtaSBkaSBtdWx0aWNvbGxpbmVhcml0w6AuCgpBZCBlc2VtcGlvLCBzZSBhYmJpYW1vIHVuYSB2YXJpYWJpbGUgImNvbG9yZSIgY29uIHRyZSBsaXZlbGxpIChyb3NzbywgdmVyZGUsIGJsdSksIGRvdnJlbW1vIGNyZWFyZSBkdWUgdmFyaWFiaWxpIGR1bW15IHBlciByYXBwcmVzZW50YXJsYS4KVW5hIHJhcHByZXNlbnRlcsOgIGlsIHJvc3NvIGUgbCdhbHRyYSBpbCB2ZXJkZS4KU2UgZW50cmFtYmUgbGUgdmFyaWFiaWxpIGR1bW15IHNvbm8gdWd1YWxpIGEgMCwgY2nDsiBzaWduaWZpY2EgY2hlIGlsIGNvbG9yZSDDqCBibHUuClF1ZXN0byBldml0YSBsYSB0cmFwIGRlbGxhIHZhcmlhYmlsZSBkdW1teS4KCmBgYHtyfQojIENyZWlhbW8gZGF0aSBmaXR0aXppCnNldC5zZWVkKDEyMykKbiA8LSAxMDAKY29sb3JlIDwtIHJlcChjKCJSb3NzbyIsICJWZXJkZSIsICJCbHUiKSwgbGVuZ3RoLm91dCA9IG4gKQp2b3RvIDwtIHJub3JtKG4sIG1lYW4gPSA1MCwgc2QgPSAxMCkKCiMgQ3JlaWFtbyB1biBkYXRhZnJhbWUgY29uIGkgZGF0aQpkYXRhIDwtIGRhdGEuZnJhbWUoY29sb3JlLCB2b3RvKQoKIyBNb2RlbGxvIGNvbiB1biBmYXR0b3JlIGNvbiBwacO5IGRpIGR1ZSBsaXZlbGxpCm1vZGVsbG8gPC0gbG0odm90byB+IGNvbG9yZSwgZGF0YSA9IGRhdGEpCgojIFZpc3VhbGl6emlhbW8gaSByaXN1bHRhdGkKc3VtbWFyeShtb2RlbGxvKQpgYGAKCkkgcmlzdWx0YXRpIGluZGljYW5vIGNoZSBpbCBjb2xvcmUgZGVsIHByb2RvdHRvIChyb3NzbyBvIHZlcmRlKSBub24gaGEgdW4gaW1wYXR0byBzaWduaWZpY2F0aXZvIHN1bCB2b3RvLgpMJ2ludGVyY2V0dGEsIGNoZSByYXBwcmVzZW50YSBpbCBjb2xvcmUgIkJsdSwiIMOoIHNpZ25pZmljYXRpdmEsIG1hIGlsIG1vZGVsbG8gbmVsIHN1byBpbnNpZW1lIG5vbiDDqCBtb2x0byBlZmZpY2FjZSBuZWwgc3BpZWdhcmUgbGEgdmFyaWF6aW9uZSBuZWkgdm90aS4KCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIENvbnRyb2xsbyBkZWwgTW9kZWxsbwoKSWwgTW9kZWwgQ2hlY2tpbmcgw6ggdW5hIGZhc2UgY3J1Y2lhbGUgbmVsbCdhbmFsaXNpIHN0YXRpc3RpY2EsIHNwZWNpYWxtZW50ZSBxdWFuZG8gc2kgYWRvdHRhIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUuCkR1cmFudGUgcXVlc3RhIGZhc2UsIHNpIHZhbHV0YSBzZSBpbCBtb2RlbGxvIHNvZGRpc2ZhIGxlIHByaW5jaXBhbGkgYXNzdW56aW9uaSBkZWkgbW9kZWxsaSBsaW5lYXJpLgpMZSBxdWF0dHJvIGFzc3VuemlvbmkgcHJpbmNpcGFsaSBkYSB2ZXJpZmljYXJlIHNvbm86CgotICAgKipMKippbmVhcml0eSAoTGluZWFyaXTDoCk6IFF1ZXN0YSBhc3N1bnppb25lIGFmZmVybWEgY2hlIGxhIHJpc3Bvc3RhICh2YXJpYWJpbGUgZGlwZW5kZW50ZSkgcHXDsiBlc3NlcmUgc2NyaXR0YSBjb21lIHVuYSBjb21iaW5hemlvbmUgbGluZWFyZSBkZWxsZSB2YXJpYWJpbGkgcHJlZGl0dGl2ZSAodmFyaWFiaWxpIGluZGlwZW5kZW50aSkuIEluIGFsdHJlIHBhcm9sZSwgaWwgbW9kZWxsbyBkb3ZyZWJiZSBlc3NlcmUgaW4gZ3JhZG8gZGkgY2F0dHVyYXJlIGlsIHJhcHBvcnRvIHRyYSBsZSB2YXJpYWJpbGkgaW4gbW9kbyBsaW5lYXJlLCBjb24gdW4gY2VydG8gZ3JhZG8gZGkgcnVtb3JlIHJlc2lkdW8uIExhIGxpbmVhcml0w6AgcHXDsiBlc3NlcmUgdmVyaWZpY2F0YSBhdHRyYXZlcnNvIGdyYWZpY2kgZGkgZGlzcGVyc2lvbmUgbyBncmFmaWNpIHJlc2lkdWkuCi0gICAqKkkqKm5kZXBlbmRlbmNlIChJbmRpcGVuZGVuemEpOiBRdWVzdGEgYXNzdW56aW9uZSByaWNoaWVkZSBjaGUgZ2xpIGVycm9yaSAocmVzaWR1aSkgZGVsIG1vZGVsbG8gc2lhbm8gaW5kaXBlbmRlbnRpIGwndW5vIGRhbGwnYWx0cm8uIENpw7Igc2lnbmlmaWNhIGNoZSBpbCB2YWxvcmUgZGkgZXJyb3JlIHBlciB1bidvc3NlcnZhemlvbmUgbm9uIMOoIGluZmx1ZW56YXRvIGRhbCB2YWxvcmUgZGkgZXJyb3JlIHBlciB1bidhbHRyYSBvc3NlcnZhemlvbmUuIEwnaW5kaXBlbmRlbnphIHB1w7IgZXNzZXJlIHZlcmlmaWNhdGEgb3NzZXJ2YW5kbyBpIGdyYWZpY2kgZGVpIHJlc2lkdWkgaW4gc2VxdWVuemEgdGVtcG9yYWxlIG8gc3BhemlhbGUsIGEgc2Vjb25kYSBkZWwgY29udGVzdG8uCi0gICAqKk4qKm9ybWFsaXR5IChOb3JtYWxpdMOgKTogTCdhc3N1bnppb25lIGRpIG5vcm1hbGl0w6AgcmljaGllZGUgY2hlIGkgcmVzaWR1aSBkZWwgbW9kZWxsbyBzZWd1YW5vIHVuYSBkaXN0cmlidXppb25lIG5vcm1hbGUuIFF1ZXN0byDDqCBpbXBvcnRhbnRlIHBlcmNow6kgbW9sdGUgcHJvY2VkdXJlIHN0YXRpc3RpY2hlIHNpIGJhc2FubyBzdWxsJ2lwb3Rlc2kgZGkgbm9ybWFsaXTDoCBkZWkgcmVzaWR1aS4gTGEgbm9ybWFsaXTDoCBwdcOyIGVzc2VyZSB2ZXJpZmljYXRhIHRyYW1pdGUgZ3JhZmljaSBxdWFudGlsZS1xdWFudGlsZSAoUVEgcGxvdCkgbyBpc3RvZ3JhbW1pIGRlaSByZXNpZHVpLgotICAgKipFKipxdWFsIFZhcmlhbmNlIChWYXJpYW56YSBVbmlmb3JtZSk6IFF1ZXN0YSBhc3N1bnppb25lLCBjaGlhbWF0YSBhbmNoZSBvbW9zY2hlZGFzdGljaXTDoCwgcmljaGllZGUgY2hlIGxhIHZhcmlhbnphIGRlaSByZXNpZHVpIHNpYSBjb3N0YW50ZSBpbiB0dXR0aSBpIGxpdmVsbGkgZGVsbGUgdmFyaWFiaWxpIHByZWRpdHRpdmUuIEluIGFsdHJlIHBhcm9sZSwgbm9uIGRvdnJlYmJlIGVzc2VyY2kgYWxjdW4gbW9kZWxsbyBkaXNjZXJuaWJpbGUgbmVsbGEgdmFyaWFuemEgZGVpIHJlc2lkdWkuIExhIHZhcmlhbnphIHVuaWZvcm1lIHB1w7IgZXNzZXJlIHZlcmlmaWNhdGEgb3NzZXJ2YW5kbyBpIGdyYWZpY2kgZGVpIHJlc2lkdWkgcmlzcGV0dG8gYWkgdmFsb3JpIHByZWRldHRpLgoKUGVyIHZlcmlmaWNhcmUgcXVlc3RlIGFzc3VuemlvbmksIGkgUmVzaWR1YWxzLWJhc2VkIGRpc3BsYXlzIChncmFmaWNpIGJhc2F0aSBzdWkgcmVzaWR1aSkgc29ubyBzcGVzc28gdXRpbGl6emF0aS4KUXVlc3RpIGluY2x1ZG9ubzoKCi0gICBTY2F0dGVycGxvdCBkZWkgcmVzaWR1aTogVW4gZ3JhZmljbyBkZWkgcmVzaWR1aSBjb250cm8gaSB2YWxvcmkgcHJldmlzdGkgbyBsZSB2YXJpYWJpbGkgcHJlZGl0dGl2ZS4gUXVlc3RvIHB1w7Igcml2ZWxhcmUgc2UgYyfDqCB1bmEgc3RydXR0dXJhIG5vbiBsaW5lYXJlIG5laSByZXNpZHVpLgotICAgR3JhZmljbyBkaSBzZXF1ZW56YSB0ZW1wb3JhbGUgZGVpIHJlc2lkdWk6IFV0aWxpenphdG8gcXVhbmRvIGkgZGF0aSBzb25vIHJhY2NvbHRpIG5lbCB0ZW1wbywgcXVlc3RvIGdyYWZpY28gcHXDsiByaXZlbGFyZSBkaXBlbmRlbnplIHRlbXBvcmFsaSBuZWkgcmVzaWR1aS4KLSAgIFFRLXBsb3QgKFF1YW50aWxlLVF1YW50aWxlIHBsb3QpOiBRdWVzdG8gZ3JhZmljbyBjb25mcm9udGEgaSBxdWFudGlsaSBkZWkgcmVzaWR1aSBjb24gcXVlbGxpIGRpIHVuYSBkaXN0cmlidXppb25lIG5vcm1hbGUuIFNlIGkgcHVudGkgZGVsIGdyYWZpY28gc2VndW9ubyB1bmEgbGluZWEgcmV0dGEsIGkgcmVzaWR1aSBzb25vIGFwcHJvc3NpbWF0aXZhbWVudGUgbm9ybWFsaS4KLSAgIElzdG9ncmFtbWEgZGVpIHJlc2lkdWk6IFVuIGlzdG9ncmFtbWEgZGVpIHJlc2lkdWkgcHXDsiBkYXJlIHVuJ2lkZWEgZGVsbGEgbG9ybyBkaXN0cmlidXppb25lIGUgbm9ybWFsaXTDoC4KClJpc3BldHRhcmUgcXVlc3RlIGFzc3Vuemlvbmkgw6ggaW1wb3J0YW50ZSBwZXIgZ2FyYW50aXJlIGNoZSBsZSBzdGltZSBkZWwgbW9kZWxsbyBzaWFubyBhZmZpZGFiaWxpIGUgY2hlIGxlIGNvbmNsdXNpb25pIHNpYW5vIHZhbGlkZS4KU2UgdW5hIG8gcGnDuSBkaSBxdWVzdGUgYXNzdW56aW9uaSBub24gc29ubyBzb2RkaXNmYXR0ZSwgcG90cmViYmVybyBlc3NlcmUgbmVjZXNzYXJpZSBjb3JyZXppb25pIGFsIG1vZGVsbG8gbyBhaSBkYXRpIHN0ZXNzaS4KCltUb3JuYSBhbGwnIFtJbmRpY2VdXQoKIyMjIFRyYW5zZm9ybWF6aW9uaQoKTGUgdHJhc2Zvcm1hemlvbmkgc29ubyB1bmEgdGVjbmljYSB1dGlsaXp6YXRhIG5lbGxhIG1vZGVsbGF6aW9uZSBzdGF0aXN0aWNhIHBlciBtb2RpZmljYXJlIGxlIHJlbGF6aW9uaSB0cmEgdmFyaWFiaWxpIGFsIGZpbmUgZGkgc29kZGlzZmFyZSBtZWdsaW8gbGUgYXNzdW56aW9uaSBkZWwgbW9kZWxsby4KTGUgdHJhc2Zvcm1hemlvbmkgcG9zc29ubyBlc3NlcmUgdXRpbGkgcXVhbmRvIGxlIHJlbGF6aW9uaSB0cmEgbGUgdmFyaWFiaWxpIG5vbiBzb25vIGxpbmVhcmkgbyBxdWFuZG8gbGUgYXNzdW56aW9uaSBkaSBvbW9zY2hlZGFzdGljaXTDoCBvIG5vcm1hbGl0w6AgZGVpIHJlc2lkdWkgbm9uIHNvbm8gc29kZGlzZmF0dGUuCkRpIHNlZ3VpdG8sIGFmZnJvbnRpYW1vIGkgc2VndWVudGkgYXJnb21lbnRpIHJlbGF0aXZpIGFsbGUgdHJhc2Zvcm1hemlvbmk6CgotICAgVmFyaWFuY2UgU3RhYmlsaXppbmcgVHJhbnNmb3JtYXRpb25zIChUcmFzZm9ybWF6aW9uaSBwZXIgU3RhYmlsaXp6YXJlIGxhIFZhcmlhbnphKTogSW4gYWxjdW5pIGNhc2ksIGxhIHZhcmlhbnphIGRlaSBkYXRpIHB1w7IgdmFyaWFyZSBpbiBtb2RvIG5vbiBjb3N0YW50ZSBjb24gaWwgY2FtYmlhcmUgZGVsIHZhbG9yZSBtZWRpby4KICAgIFF1ZXN0byBmZW5vbWVubyDDqCBub3RvIGNvbWUgZXRlcm9zY2hlZGFzdGljaXTDoC4KICAgIExlIHRyYXNmb3JtYXppb25pIHBvc3Nvbm8gZXNzZXJlIHV0aWxpenphdGUgcGVyIHN0YWJpbGl6emFyZSBsYSB2YXJpYW56YSwgcmVuZGVuZG8gbGEgcmVsYXppb25lIHRyYSBpbCB2YWxvcmUgbWVkaW8gZSBsYSB2YXJpYW56YSBwacO5IGNvc3RhbnRlLgogICAgVW4gZXNlbXBpbyBjb211bmUgw6ggbGEgdHJhc2Zvcm1hemlvbmUgZGkgQm94LUNveC4KCi0gICBCb3gtQ294IFRyYW5zZm9ybTogTGEgdHJhc2Zvcm1hemlvbmUgZGkgQm94LUNveCDDqCB1bmEgdGVjbmljYSB1dGlsaXp6YXRhIHBlciBzdGFiaWxpenphcmUgbGEgdmFyaWFuemEgZSByZW5kZXJlIGkgZGF0aSBhcHByb3NzaW1hdGl2YW1lbnRlIG5vcm1hbGkuCiAgICDDiCBkZWZpbml0YSBjb21lOgoKJCQgCnkoXGxhbWJkYSkgPSBcYmVnaW57Y2FzZXN9IFxmcmFjeyh5XlxsYW1iZGEgLSAxKX17XGxhbWJkYX0gJiBcdGV4dHtzZSB9IFxsYW1iZGEgXG5lcSAwIFxcCiAgICBcbG9nKHkpICYgXHRleHR7c2UgfSBcbGFtYmRhID0gMApcZW5ke2Nhc2VzfQokJAoKRG92ZSB5IHNvbm8gaSBkYXRpIG9yaWdpbmFsaSBlIM67IMOoIGlsIHBhcmFtZXRybyBkaSB0cmFzZm9ybWF6aW9uZS4Kw4ggcG9zc2liaWxlIGNhbGNvbGFyZSBpbCB2YWxvcmUgb3R0aW1hbGUgZGkgzrsgY2hlIG1hc3NpbWl6emEgbGEgbm9ybWFsaXTDoCBkZWkgZGF0aS4KCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoTUFTUykKbGlicmFyeShncmlkRXh0cmEpCgojIEdlbmVyYSBkYXRpIGNhc3VhbGkKc2V0LnNlZWQoMTIzKQpkYXRhIDwtIGRhdGEuZnJhbWUoeSA9IHJnYW1tYSgxMDAsIHNoYXBlID0gMiwgc2NhbGUgPSAxKSkKCiMgQXBwbGljYSBsYSB0cmFzZm9ybWF6aW9uZSBkaSBCb3gtQ294CnJlc3VsdCA8LSBib3hjb3goeSB+IDEsIGRhdGEgPSBkYXRhKQpsYW1iZGEgPC0gcmVzdWx0JHhbd2hpY2gubWF4KHJlc3VsdCR5KV0KdHJhbnNmb3JtZWRfZGF0YSA8LSBpZiAobGFtYmRhID09IDApIGxvZyhkYXRhJHkpIGVsc2UgKChkYXRhJHlebGFtYmRhIC0gMSkgLyBsYW1iZGEpCgojIFZpc3VhbGl6emEgaWwgdmFsb3JlIG90dGltYWxlIGRpIGxhbWJkYQpjYXQoIlZhbG9yZSBvdHRpbWFsZSBkaSBsYW1iZGE6ICIsIGxhbWJkYSwgIlxuIikKCiMgQ3JlYSB1biBkYXRhZnJhbWUgY29uIGkgZGF0aSBvcmlnaW5hbGkgZSB0cmFzZm9ybWF0aQpwbG90X2RhdGEgPC0gZGF0YS5mcmFtZShPcmlnaW5hbCA9IGRhdGEkeSwgVHJhbnNmb3JtZWQgPSB0cmFuc2Zvcm1lZF9kYXRhKQoKIyBQbG90dGEgaSBkYXRpIG9yaWdpbmFsaQpwbG90X29yaWdpbmFsIDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gT3JpZ2luYWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC43KSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXppb25lIGRlaSBkYXRpIG9yaWdpbmFsaSIpCgojIFBsb3R0YSBpIGRhdGkgdHJhc2Zvcm1hdGkKcGxvdF90cmFuc2Zvcm1lZCA8LSBnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IFRyYW5zZm9ybWVkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBmaWxsID0gImdyZWVuIiwgYWxwaGEgPSAwLjcpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1emlvbmUgZGVpIGRhdGkgdHJhc2Zvcm1hdGkiKQoKIyBNb3N0cmEgaSBncmFmaWNpIHN1bGxhIHN0ZXNzYSByaWdhCmdyaWQuYXJyYW5nZShwbG90X29yaWdpbmFsLCBwbG90X3RyYW5zZm9ybWVkLCBuY29sID0gMikKYGBgCgotICAgUG9seW5vbWlhbHMgKFBvbGlub21pKTogTGUgdHJhc2Zvcm1hemlvbmkgcG9saW5vbWlhbGkgY29uc2VudG9ubyBkaSBtb2RlbGxhcmUgcmVsYXppb25pIG5vbiBsaW5lYXJpIHRyYSB2YXJpYWJpbGkuIMOIIHBvc3NpYmlsZSBhZ2dpdW5nZXJlIHRlcm1pbmkgcG9saW5vbWlhbGkgYWwgbW9kZWxsbyBkaSByZWdyZXNzaW9uZSBwZXIgY2F0dHVyYXJlIGN1cnZlIG8gcmVsYXppb25pIHBpw7kgY29tcGxlc3NlLiBBZCBlc2VtcGlvLCBzaSBwb3Nzb25vIHV0aWxpenphcmUgcG9saW5vbWkgZGkgc2Vjb25kbyBncmFkbyBwZXIgbW9kZWxsYXJlIHVuYSByZWxhemlvbmUgcXVhZHJhdGljYSB0cmEgdW5hIHZhcmlhYmlsZSBpbmRpcGVuZGVudGUgZSBsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZS4gTCdhZ2dpdW50YSBkaSB0ZXJtaW5pIHBvbGlub21pYWxpIHB1w7IgbWlnbGlvcmFyZSBsJ2FkYXR0YW1lbnRvIGRlbCBtb2RlbGxvIGFpIGRhdGksIG1hIMOoIGltcG9ydGFudGUgZXZpdGFyZSBkaSBhZ2dpdW5nZXJlIHRyb3BwaSB0ZXJtaW5pIHBvbGlub21pYWxpIHBlciBldml0YXJlIGwnb3ZlcmZpdHRpbmcuCgpgYGB7cn0KIyBNb2RlbGxvIGxpbmVhcmUgY29uIHVuIHRlcm1pbmUgcG9saW5vbWlhbGUgZGkgc2Vjb25kbyBncmFkbwptb2RlbCA8LSBsbSh5IH4geCArIEkoeF4yKSwgZGF0YSA9IGRhdGEpCmBgYAoKLSAgIFRyYW5zZm9ybWF0aW9ucyBvZiBQcmVkaWN0b3IgVmFyaWFibGVzIChUcmFzZm9ybWF6aW9uaSBkZWxsZSBWYXJpYWJpbGkgUHJlZGl0dGl2ZSk6IExlIHRyYXNmb3JtYXppb25pIGRlbGxlIHZhcmlhYmlsaSBwcmVkaXR0aXZlIHNvbm8gdXRpbGl6emF0ZSBwZXIgYWRhdHRhcmUgaSBkYXRpIGluIG1vZG8gY2hlIHNvZGRpc2Zpbm8gbWVnbGlvIGxlIGFzc3VuemlvbmkgZGVsIG1vZGVsbG8uIFF1ZXN0ZSB0cmFzZm9ybWF6aW9uaSBjb2ludm9sZ29ubyBsYSBtb2RpZmljYSBkZWxsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpIHBpdXR0b3N0byBjaGUgZGVsbGEgdmFyaWFiaWxlIGRpcGVuZGVudGUuIFBvc3Nvbm8gZXNzZXJlIHV0aWxpenphdGUgcGVyIHJlbmRlcmUgbGUgcmVsYXppb25pIHRyYSBsZSB2YXJpYWJpbGkgcGnDuSBsaW5lYXJpIG8gcGVyIHN0YWJpbGl6emFyZSBsYSB2YXJpYW56YS4gQWQgZXNlbXBpbywgw6ggcG9zc2liaWxlIGFwcGxpY2FyZSB1bmEgdHJhc2Zvcm1hemlvbmUgbG9nYXJpdG1pY2EgbyB1bmEgcmFkaWNlIHF1YWRyYXRhIGEgdW5hIHZhcmlhYmlsZSBwcmVkaXR0aXZhIHBlciByZW5kZXJsYSBwacO5IGxpbmVhcmUgbmVpIGNvbmZyb250aSBkZWxsYSB2YXJpYWJpbGUgZGlwZW5kZW50ZS4KCmBgYHtyfQojIENyZWlhbW8gZGF0aSBmaXR0aXppCnNldC5zZWVkKDEyMykKWCA8LSBybm9ybSgxMDAsIG1lYW4gPSAxMCwgc2QgPSAyKQpZIDwtIDIgKiBYICsgcm5vcm0oMTAwLCBtZWFuID0gMCwgc2QgPSAxKQoKIyBDcmVpYW1vIHVuIGRhdGFmcmFtZSBjb24gaSBkYXRpCmRhdGEgPC0gZGF0YS5mcmFtZShYLCBZKQoKIyBNb2RlbGxvIGxpbmVhcmUgc2VuemEgdHJhc2Zvcm1hemlvbmUKbW9kZWxfbm9fdHJhbnNmb3JtIDwtIGxtKFkgfiBYLCBkYXRhID0gZGF0YSkKCiMgVmlzdWFsaXp6aWFtbyBpbCBzdW1tYXJ5IGRlbCBtb2RlbGxvIHNlbnphIHRyYXNmb3JtYXppb25lCnN1bW1hcnkobW9kZWxfbm9fdHJhbnNmb3JtKQoKIyBUcmFzZm9ybWlhbW8gbGEgdmFyaWFiaWxlIFggYXBwbGljYW5kbyBpbCBsb2dhcml0bW8KZGF0YSRYX3RyYW5zZm9ybWVkIDwtIGxvZyhkYXRhJFgpCgojIE1vZGVsbG8gbGluZWFyZSBjb24gbGEgdmFyaWFiaWxlIFggdHJhc2Zvcm1hdGEKbW9kZWxfd2l0aF90cmFuc2Zvcm0gPC0gbG0oWSB+IFhfdHJhbnNmb3JtZWQsIGRhdGEgPSBkYXRhKQoKIyBWaXN1YWxpenppYW1vIGlsIHN1bW1hcnkgZGVsIG1vZGVsbG8gY29uIGxhIHZhcmlhYmlsZSBYIHRyYXNmb3JtYXRhCnN1bW1hcnkobW9kZWxfd2l0aF90cmFuc2Zvcm0pCmBgYAoKTGUgdHJhc2Zvcm1hemlvbmkgc29ubyBzdHJ1bWVudGkgcG90ZW50aSBwZXIgYWRhdHRhcmUgaSBtb2RlbGxpIGFpIGRhdGkgaW4gbW9kbyBwacO5IGFjY3VyYXRvIHF1YW5kbyBsZSByZWxhemlvbmkgdHJhIHZhcmlhYmlsaSBub24gc29ubyBsaW5lYXJpIG8gcXVhbmRvIGxlIGFzc3VuemlvbmkgZGVsIG1vZGVsbG8gbm9uIHNvbm8gc29kZGlzZmF0dGUuClR1dHRhdmlhLCDDqCBpbXBvcnRhbnRlIHNjZWdsaWVyZSBjb24gYXR0ZW56aW9uZSBsZSB0cmFzZm9ybWF6aW9uaSBwZXIgZXZpdGFyZSBpbCBzb3ZyYWRhdHRhbWVudG8gZSBnYXJhbnRpcmUgY2hlIGkgcmlzdWx0YXRpIHNpYW5vIGludGVycHJldGFiaWxpLgoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIyMgTXVsdGljb2xsaW5lYXJpdMOgCgpMYSBtdWx0aWNvbGxpbmVhcml0w6Agc2kgdmVyaWZpY2EgcXVhbmRvIGR1ZSBvIHBpw7kgdmFyaWFiaWxpIGluZGlwZW5kZW50aSBpbiB1biBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIHNvbm8gZm9ydGVtZW50ZSBjb3JyZWxhdGUgdHJhIGxvcm8uClF1ZXN0YSBjb3JyZWxhemlvbmUgdHJhIGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgcHXDsiByZW5kZXJlIGRpZmZpY2lsZSBsJ2ludGVycHJldGF6aW9uZSBkZWwgbW9kZWxsbyBlIHBvcnRhcmUgYSBzdGltZSBwb2NvIGFmZmlkYWJpbGkgZGVpIGNvZWZmaWNpZW50aSBkaSByZWdyZXNzaW9uZS4KTGEgcHJlc2VuemEgZGkgbXVsdGljb2xsaW5lYXJpdMOgIHB1w7IgY2F1c2FyZSB1biBhdW1lbnRvIGRlbCBWYXJpYW5jZSBJbmZsYXRpb24gRmFjdG9yIChWSUYpLCB1bmEgbWlzdXJhIGNvbXVuZSB1dGlsaXp6YXRhIHBlciB2YWx1dGFyZSBsYSBtdWx0aWNvbGxpbmVhcml0w6AgdHJhIGxlIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkgaW4gdW4gbW9kZWxsbyBkaSByZWdyZXNzaW9uZS4KVW4gYWx0byBWSUYgcGVyIHVuYSB2YXJpYWJpbGUgaW5kaWNhIGNoZSBxdWVsbGEgdmFyaWFiaWxlIMOoIGZvcnRlbWVudGUgY29ycmVsYXRhIGNvbiBsZSBhbHRyZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpIG5lbCBtb2RlbGxvLgoKKipWYXJpYW5jZSBJbmZsYXRpb24gRmFjdG9yOioqCgpJbCBWSUYgZGkgY2lhc2N1bmEgdmFyaWFiaWxlIGluZGlwZW5kZW50ZSDDqCBjYWxjb2xhdG8gY29tZSBpbCByYXBwb3J0byBkZWxsYSB2YXJpYW56YSBkZWxsJ2Vycm9yZSBzdGFuZGFyZCBkZWwgY29lZmZpY2llbnRlIGRpIHJlZ3Jlc3Npb25lIHN0aW1hdG8gcGVyIHF1ZWxsYSB2YXJpYWJpbGUgcmlzcGV0dG8gYWxsYSB2YXJpYW56YSBkZWxsJ2Vycm9yZSBzdGFuZGFyZCBzZSBsYSB2YXJpYWJpbGUgZm9zc2Ugc3RhdGEgY29tcGxldGFtZW50ZSBub24gY29ycmVsYXRhIGFsbGUgYWx0cmUgdmFyaWFiaWxpIGluZGlwZW5kZW50aS4KSW4gZ2VuZXJhbGUsIHVuIFZJRiBzdXBlcmlvcmUgYSA1IG8gMTAgw6ggc3Blc3NvIGNvbnNpZGVyYXRvIHVuIHNlZ25vIGRpIG11bHRpY29sbGluZWFyaXTDoCBzaWduaWZpY2F0aXZhLgoKJCQgClZJRl9pID0gKFheVFgpX3tpKzEsaSsxfV57LTF9Km5zXjJfe1hfaX0gXCBcICBvcHB1cmUgXCBcIFZJRl9pID0gXGZyYWN7MX17MS1SXjJfaX0KJCQKYGBge3J9CiMgTG9hZCB0aGUgbmVjZXNzYXJ5IGxpYnJhcnkKbGlicmFyeShjYXIpCgojIENyZWF0ZSBhIHNhbXBsZSBkYXRhc2V0IHdpdGggbXVsdGlwbGUgcHJlZGljdG9yIHZhcmlhYmxlcwpzZXQuc2VlZCgxMjMpCmRhdGEgPC0gZGF0YS5mcmFtZSgKICBYMSA9IHJub3JtKDEwMCksCiAgWDIgPSBybm9ybSgxMDApLAogIFgzID0gcm5vcm0oMTAwKSwKICBYNCA9IHJub3JtKDEwMCkKKQoKIyBBZGQgYSBkZXBlbmRlbnQgdmFyaWFibGUgKHJlc3BvbnNlKQpkYXRhJFkgPC0gMiAqIGRhdGEkWDEgKyAzICogZGF0YSRYMiArIDEuNSAqIGRhdGEkWDMgKyBybm9ybSgxMDApCgojIEZpdCBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsCm1vZGVsIDwtIGxtKFkgfiBYMSArIFgyICsgWDMgKyBYNCwgZGF0YSA9IGRhdGEpCgojIENhbGN1bGF0ZSBWSUYKdmlmX3ZhbHVlcyA8LSB2aWYobW9kZWwpCgojIFByaW50IHRoZSBWSUYgdmFsdWVzCnZpZl92YWx1ZXMKYGBgCgpUdXR0aSBpIHZhbG9yaSBWSUYgc29ubyB2aWNpbmkgYSAxLCBpbCBjaGUgc3VnZ2VyaXNjZSBjaGUgbm9uIGMnw6ggdW5hIGZvcnRlIG11bHRpY29sbGluZWFyaXTDoCB0cmEgbGUgdmFyaWFiaWxpIHByZWRpdHRpdmUgWDEsIFgyLCBYMyBlIFg0LgpRdWVzdG8gw6ggdW4gYnVvbiBzZWdubywgcG9pY2jDqSBzaWduaWZpY2EgY2hlIGxlIHZhcmlhYmlsaSBub24gc29ubyBmb3J0ZW1lbnRlIGNvcnJlbGF0ZSB0cmEgbG9yby4KClZhbG9yaSBWSUYgcGnDuSBlbGV2YXRpIGluZGljYW5vIHVuYSBtdWx0aWNvbGxpbmVhcml0w6AgcGnDuSBmb3J0ZSwgZSB2YWxvcmkgYWwgZGkgc29wcmEgZGkgdW5hIGNlcnRhIHNvZ2xpYSAoYWQgZXNlbXBpbywgVklGIFw+IDUpIHBvc3Nvbm8gc3VnZ2VyaXJlIGxhIG5lY2Vzc2l0w6AgZGkgYWZmcm9udGFyZSBsYSBjb2xsaW5lYXJpdMOgLCBhZCBlc2VtcGlvLCByaW11b3ZlbmRvIHVuYSBkZWxsZSB2YXJpYWJpbGkgcHJlZGl0dGl2ZSBjb3JyZWxhdGUuCgpbVG9ybmEgYWxsJyBbSW5kaWNlXV0KCiMjIyBQdW50aSBJbmZsdWVudGkKCkkgcHVudGkgaW5mbHVlbnRpIHNpIHJpZmVyaXNjb25vIGEgb3NzZXJ2YXppb25pIG5laSBkYXRpIGNoZSBoYW5ubyB1biBpbXBhdHRvIHNpZ25pZmljYXRpdm8gc3VpIHJpc3VsdGF0aSBkaSB1bidhbmFsaXNpIHN0YXRpc3RpY2EsIGNvbWUgdW5hIHJlZ3Jlc3Npb25lIGxpbmVhcmUuClF1ZXN0aSBwdW50aSBwb3Nzb25vIGluZmx1ZW56YXJlIGxhIHN0aW1hIGRlaSBwYXJhbWV0cmkgZGVsIG1vZGVsbG8sIGkgcmVzaWR1aSwgaSB2YWxvcmkgcCwgbCdSLXNxdWFyZWQgZSBhbHRyZSBzdGF0aXN0aWNoZSBkaSByaWxldmFuemEuCkNpIHNvbm8gZGl2ZXJzZSBtZXRyaWNoZSB1dGlsaXp6YXRlIHBlciBpZGVudGlmaWNhcmUgaSBwdW50aSBpbmZsdWVudGksIHRyYSBjdWkgU3RhbmRhcmRpemVkIFJlc2lkdWFscywgU3R1ZGVudGl6ZWQgUmVzaWR1YWxzIGUgQ29vaydzIERpc3RhbmNlLgoKLSAgIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMgKFJlc2lkdWkgU3RhbmRhcmRpenphdGkpOiBRdWVzdGkgc29ubyBpIHJlc2lkdWkgZGl2aXNpIHBlciBsYSBkZXZpYXppb25lIHN0YW5kYXJkIGRlaSByZXNpZHVpLiBVbiByZXNpZHVvIHN0YW5kYXJkaXp6YXRvIMOoIHVuYSBtaXN1cmEgZGkgcXVhbnRvIHVuIHB1bnRvIGRhdG8gc2kgZGlzY29zdGkgZGFsbGEgbGluZWEgZGkgcmVncmVzc2lvbmUgaW4gdGVybWluaSBkaSBkZXZpYXppb25pIHN0YW5kYXJkLiBJIHB1bnRpIGNvbiByZXNpZHVpIHN0YW5kYXJkaXp6YXRpIG1vbHRvIGdyYW5kaSAocG9zaXRpdmkgbyBuZWdhdGl2aSkgc29ubyBjb25zaWRlcmF0aSBpbmZsdWVudGkuCi0gICBTdHVkZW50aXplZCBSZXNpZHVhbHMgKFJlc2lkdWkgU3R1ZGVudGl6emF0aSk6IFF1ZXN0aSBzb25vIGkgcmVzaWR1aSBkaXZpc2kgcGVyIHVuYSBzdGltYSBkZWxsYSBkZXZpYXppb25lIHN0YW5kYXJkIGRlbGwnZXJyb3JlIHJlc2lkdW8uIEkgcmVzaWR1aSBzdHVkZW50aXp6YXRpIHNvbm8gdXRpbGl6emF0aSBwZXIgdmFsdXRhcmUgcXVhbnRvIHVuIHB1bnRvIGRhdG8gc2lhIGluZmx1ZW50ZSBjb25zaWRlcmFuZG8gbCdlZmZldHRvIGRlbGxlIGFsdHJlIG9zc2VydmF6aW9uaSBuZWwgZGF0YXNldC4gSSBwdW50aSBjb24gcmVzaWR1aSBzdHVkZW50aXp6YXRpIHNpZ25pZmljYXRpdmFtZW50ZSBncmFuZGkgaW4gdmFsb3JlIGFzc29sdXRvIHNvbm8gY29uc2lkZXJhdGkgaW5mbHVlbnRpLgotICAgQ29vaydzIERpc3RhbmNlIChEaXN0YW56YSBkaSBDb29rKTogQ29vaydzIERpc3RhbmNlIMOoIHVuYSBtZXRyaWNhIGNoZSBjb21iaW5hIGwnZWZmZXR0byBkaSB1biBwdW50byBzdWkgcGFyYW1ldHJpIGRlbCBtb2RlbGxvIGUgaWwgc3VvIGVmZmV0dG8gc3VpIHJlc2lkdWkuIEkgcHVudGkgY29uIENvb2sncyBEaXN0YW5jZSBtb2x0byBncmFuZGkgc29ubyBjb25zaWRlcmF0aSBpbmZsdWVudGkuIENvb2sncyBEaXN0YW5jZSDDqCBzcGVzc28gdXRpbGl6emF0byBwZXIgaWRlbnRpZmljYXJlIHB1bnRpIGNoZSwgc2Ugcmltb3NzaSwgYXZyZWJiZXJvIHVuIGltcGF0dG8gc2lnbmlmaWNhdGl2byBzdWkgcmlzdWx0YXRpIGRlbCBtb2RlbGxvLgoKTmVsIGNvbnRlc3RvIGRlbGxhIHJlZ3Jlc3Npb25lLCBpIHB1bnRpIGluZmx1ZW50aSBwb3Nzb25vIGRlcml2YXJlIGRhIG91dGxpZXIgbmVpIGRhdGksIGRhdGkgZXJyYXRpIG8gcHVudGkgY2hlIGluZmx1ZW56YW5vIG5vdGV2b2xtZW50ZSBsYSBzdGltYSBkZWkgcGFyYW1ldHJpLgpJZGVudGlmaWNhcmUgZSB0cmF0dGFyZSBpIHB1bnRpIGluZmx1ZW50aSDDqCBpbXBvcnRhbnRlIHBlciBnYXJhbnRpcmUgY2hlIGlsIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUgc2lhIGFmZmlkYWJpbGUgZSByYXBwcmVzZW50aSBhY2N1cmF0YW1lbnRlIGkgZGF0aS4KTGEgcmltb3ppb25lIGRpIHB1bnRpIGluZmx1ZW50aSBwdcOyIG1pZ2xpb3JhcmUgbGEgYm9udMOgIGRpIGFkYXR0YW1lbnRvIGRlbCBtb2RlbGxvIGUgbCdhY2N1cmF0ZXp6YSBkZWxsZSBwcmV2aXNpb25pLgoKYGBge3J9CiMgQ2FyaWNoaWFtbyBpbCBkYXRhc2V0IGRpIGVzZW1waW8KZGF0YShtdGNhcnMpCgojIEFkYXR0aWFtbyB1biBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUKbW9kZWwgPC0gbG0obXBnIH4gd3QgKyBocCwgZGF0YSA9IG10Y2FycykKCiMgQ2FsY29saWFtbyBpIHJlc2lkdWkgc3RhbmRhcmRpenphdGkKc3RhbmRhcmRpemVkX3Jlc2lkdWFscyA8LSByc3RhbmRhcmQobW9kZWwpCgojIElkZW50aWZpY2hpYW1vIGkgcHVudGkgaW5mbHVlbnRpIGJhc2F0aSBzdWkgcmVzaWR1aSBzdGFuZGFyZGl6emF0aQppbmZsdWVudGlhbF9wb2ludHMgPC0gd2hpY2goYWJzKHN0YW5kYXJkaXplZF9yZXNpZHVhbHMpID4gMikKCiMgVmlzdWFsaXp6aWFtbyBnbGkgaW5kaWNpIGRlaSBwdW50aSBpbmZsdWVudGkKY2F0KCJQdW50aSBpbmZsdWVudGkgYmFzYXRpIHN1aSByZXNpZHVpIHN0YW5kYXJkaXp6YXRpOiIsIGluZmx1ZW50aWFsX3BvaW50cywgIlxuIikKCiMgQ2FsY29saWFtbyBDb29rJ3MgRGlzdGFuY2UKY29va19kaXN0YW5jZSA8LSBjb29rcy5kaXN0YW5jZShtb2RlbCkKCiMgSWRlbnRpZmljaGlhbW8gaSBwdW50aSBpbmZsdWVudGkgYmFzYXRpIHN1IENvb2sncyBEaXN0YW5jZQppbmZsdWVudGlhbF9wb2ludHNfY29vayA8LSB3aGljaChjb29rX2Rpc3RhbmNlID4gNCAvIGxlbmd0aChjb29rX2Rpc3RhbmNlKSkKCiMgVmlzdWFsaXp6aWFtbyBnbGkgaW5kaWNpIGRlaSBwdW50aSBpbmZsdWVudGkgYmFzYXRpIHN1IENvb2sncyBEaXN0YW5jZQpjYXQoIlB1bnRpIGluZmx1ZW50aSBiYXNhdGkgc3UgQ29vaydzIERpc3RhbmNlOiIsIGluZmx1ZW50aWFsX3BvaW50c19jb29rLCAiXG4iKQoKcGFyKG1mcm93ID0gYygxLDIpKQojIEdyYWZpY28gZGVpIHB1bnRpIGNvbiBldmlkZW56aWF6aW9uZSBkZWkgcHVudGkgaW5mbHVlbnRpCnBsb3QobXRjYXJzJHd0LCBtdGNhcnMkbXBnLCBwY2ggPSAxNiwgbWFpbiA9ICJQdW50aSBJbmZsdWVudGkgKFN0YW4gZSBTdHVkKSIsCiAgICAgeGxhYiA9ICJQZXNvICh3dCkiLCB5bGFiID0gIk1pZ2xpYSBwZXIgZ2FsbG9uZSAobXBnKSIpCnBvaW50cyhtdGNhcnMkd3RbaW5mbHVlbnRpYWxfcG9pbnRzXSwgbXRjYXJzJG1wZ1tpbmZsdWVudGlhbF9wb2ludHNdLCBwY2ggPSAxNiwgY29sID0gInJlZCIsIGNleCA9IDEuNSkKCgpwbG90KG10Y2FycyR3dCwgbXRjYXJzJG1wZywgcGNoID0gMTYsIG1haW4gPSAiUHVudGkgSW5mbHVlbnRpIChDb29rKSIsCiAgICAgeGxhYiA9ICJQZXNvICh3dCkiLCB5bGFiID0gIk1pZ2xpYSBwZXIgZ2FsbG9uZSAobXBnKSIpCnBvaW50cyhtdGNhcnMkd3RbaW5mbHVlbnRpYWxfcG9pbnRzX2Nvb2tdLCBtdGNhcnMkbXBnW2luZmx1ZW50aWFsX3BvaW50c19jb29rXSwgcGNoID0gMTYsIGNvbCA9ICJyZWQiLCBjZXggPSAxLjUpCgpgYGAKCioqTGV2ZXJhZ2U6KioKCklsICJMZXZlcmFnZSIgw6ggdW5hIG1pc3VyYSB1dGlsaXp6YXRhIG5lbGwnYW5hbGlzaSBkZWkgZGF0aSBzdGF0aXN0aWNpIHBlciBpZGVudGlmaWNhcmUgcHVudGkgaW5mbHVlbnRpIG8gb3NzZXJ2YXppb25pIGF0aXBpY2hlIGluIHVuIG1vZGVsbG8gZGkgcmVncmVzc2lvbmUuClF1ZXN0YSBtaXN1cmEgdmFsdXRhIHF1YW50byB1bidvc3NlcnZhemlvbmUgcHXDsiBpbmZsdWVuemFyZSBpIHJpc3VsdGF0aSBkZWwgbW9kZWxsbywgaW4gcGFydGljb2xhcmUgaSBjb2VmZmljaWVudGkgZGkgcmVncmVzc2lvbmUuCklsIGxldmVyYWdlIMOoIGNhbGNvbGF0byBzdWxsYSBiYXNlIGRlbGxlIHZhcmlhYmlsaSBwcmVkaXR0aXZlIGUgcHXDsiBlc3NlcmUgdXRpbGl6emF0byBwZXIgaWRlbnRpZmljYXJlIGxlIG9zc2VydmF6aW9uaSBjaGUgaGFubm8gdW4gaW1wYXR0byBzaWduaWZpY2F0aXZvIHN1bCBtb2RlbGxvLgoKSWRlbnRpZmljYXppb25lIGRlaSBwdW50aSBpbmZsdWVudGk6IEkgcHVudGkgY29uIHVuIHZhbG9yZSBkaSBsZXZlcmFnZSBzaWduaWZpY2F0aXZhbWVudGUgcGnDuSBhbHRvIGRlZ2xpIGFsdHJpIHNvbm8gcXVlbGxpIGNoZSBwb3Nzb25vIGluZmx1ZW56YXJlIG5vdGV2b2xtZW50ZSBpbCBtb2RlbGxvLgpQdW9pIHN0YWJpbGlyZSB1bmEgc29nbGlhIGFyYml0cmFyaWEgbyB1dGlsaXp6YXJlIG1ldG9kaSBzdGF0aXN0aWNpIHBlciBkZXRlcm1pbmFyZSBxdWFsaSBwdW50aSBzb25vIGluZmx1ZW50aS4KQWQgZXNlbXBpbywgaSBwdW50aSBjb24gbGV2ZXJhZ2Ugc3VwZXJpb3JlIGEgMiB2b2x0ZSBsYSBtZWRpYSBwb3Nzb25vIGVzc2VyZSBjb25zaWRlcmF0aSBpbmZsdWVudGkuCgpFc2FtZSBkZWkgcHVudGkgaW5mbHVlbnRpOiBVbmEgdm9sdGEgaWRlbnRpZmljYXRpIGkgcHVudGkgaW5mbHVlbnRpLCDDqCBwb3NzaWJpbGUgZXNhbWluYXJsaSB1bHRlcmlvcm1lbnRlIHBlciBkZXRlcm1pbmFyZSBzZSBzb25vIGVmZmV0dGl2YW1lbnRlIG91dGxpZXJzIG8gZXJyb3JpIGRpIG1pc3VyYXppb25lLgpQb3RyZXN0aSB2b2xlciBlc2FtaW5hcmUgbGUgb3NzZXJ2YXppb25pIGNvbiBlbGV2YXRlIGRpZmZlcmVuemUgdHJhIGkgdmFsb3JpIG9zc2VydmF0aSBlIHF1ZWxsaSBwcmV2aXN0aSBkYWwgbW9kZWxsby4KCsOIIGltcG9ydGFudGUgbm90YXJlIGNoZSBsYSByaW1vemlvbmUgZGVpIHB1bnRpIGluZmx1ZW50aSBkb3ZyZWJiZSBlc3NlcmUgZWZmZXR0dWF0YSBjb24gY2F1dGVsYSBlIHNvbG8gc2UgYyfDqCB1bmEgZ2l1c3RpZmljYXppb25lIHZhbGlkYS4KSW4gYWxjdW5pIGNhc2ksIHBvdHJlc3RpIHNjZWdsaWVyZSBkaSBtYW50ZW5lcmUgaSBwdW50aSBpbmZsdWVudGkgbmVsIG1vZGVsbG8gc2Ugcml0aWVuaSBjaGUgcmFwcHJlc2VudGlubyBpbmZvcm1hemlvbmkgc2lnbmlmaWNhdGl2ZSBvIHNlIGhhbm5vIHVuYSBzcGllZ2F6aW9uZSBwbGF1c2liaWxlLgoKYGBge3J9CiMgR2VuZXJpYW1vIGRhdGkgY2FzdWFsaQpzZXQuc2VlZCgxMjMpCm4gPC0gMTAwCnggPC0gcm5vcm0obikKeSA8LSAyICogeCArIHJub3JtKG4pCgojIEFkYXR0aWFtbyB1biBtb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUKbW9kZWwgPC0gbG0oeSB+IHgpCgojIENhbGNvbGlhbW8gaSB2YWxvcmkgZGkgbGV2ZXJhZ2UKbGV2ZXJhZ2UgPC0gaGF0dmFsdWVzKG1vZGVsKQoKIyBJZGVudGlmaWNoaWFtbyBpIHB1bnRpIGluZmx1ZW50aQppbmZsX3BvaW50cyA8LSB3aGljaChsZXZlcmFnZSA+IDIgKiBtZWFuKGxldmVyYWdlKSkKCiMgVmlzdWFsaXp6aWFtbyBpIHB1bnRpIGluZmx1ZW50aQpwcmludChpbmZsX3BvaW50cykKCnBhcihtZnJvdyA9IGMoMSwyKSkKIyBQbG90IGRlbCBncmFmaWNvCnBsb3QoeCwgeSkKcG9pbnRzKHhbaW5mbF9wb2ludHNdLCB5W2luZmxfcG9pbnRzXSwgY29sID0gImJsdWUiLCBwY2ggPSAxOSkKCiMgUGxvdCBkZWwgTGV2ZXJhZ2UKcGxvdCh4LCBsZXZlcmFnZSkKcG9pbnRzKHhbaW5mbF9wb2ludHNdLCBsZXZlcmFnZVtpbmZsX3BvaW50c10sIGNvbCA9ICJibHVlIiwgcGNoID0gMTkpCmBgYAoKTm90YSBjaGUgbmVsbCdlc2VtcGlvIGFiYmlhbW8gdXRpbGl6emF0byB1bmEgc29nbGlhIGRpIGxldmVyYWdlIGFyYml0cmFyaWEgKDIgdm9sdGUgbGEgbWVkaWEpIHBlciBpZGVudGlmaWNhcmUgaSBwdW50aSBpbmZsdWVudGkuCkluIHVuJ2FwcGxpY2F6aW9uZSBwcmF0aWNhLCDDqCBjb25zaWdsaWFiaWxlIGNvbnNpZGVyYXJlIGxhIHNvZ2xpYSBpbiBiYXNlIGFsIGNvbnRlc3RvIGRlbCBwcm9ibGVtYSBlIGFsbCdhbmFsaXNpIGRlaSBkYXRpLgoKW1Rvcm5hIGFsbCcgW0luZGljZV1dCgojIE1vZGVsbGkgTGluZWFyaSBHZW5lcmFsaXp6YXRpIHsjbW9kZWxsaS1saW5lYXJpLWdlbmVyYWxpenphdGktZ2xtfQoKSSBHTE0gZXN0ZW5kb25vIGlsIGZyYW1ld29yayBkZWxsYSByZWdyZXNzaW9uZSBsaW5lYXJlIHBlciBnZXN0aXJlIHVuJ2FtcGlhIGdhbW1hIGRpIGRpc3RyaWJ1emlvbmkgZGVpIGRhdGkgZSB0aXBvbG9naWUgZGkgcmlzcG9zdGUuCkEgZGlmZmVyZW56YSBkZWxsYSByZWdyZXNzaW9uZSBsaW5lYXJlIHRyYWRpemlvbmFsZSwgaSBHTE0gcG9zc29ubyBhY2NvbW9kYXJlIGRpc3RyaWJ1emlvbmkgZGkgZXJyb3JpIG5vbiBub3JtYWxpIGUgbW9kZWxsYXJlIHJlbGF6aW9uaSB0cmEgcHJlZGl0dG9yaSBlIHJpc3Bvc3RlIGF0dHJhdmVyc28gdW5hIGZ1bnppb25lIGRpIGNvbGxlZ2FtZW50by4KClVuIEdMTSDDqCBjYXJhdHRlcml6emF0byBkYSB0cmUgY29tcG9uZW50aSBwcmluY2lwYWxpOgoKMS4gICoqQ29tcG9uZW50ZSBDYXN1YWxlIChEaXN0cmlidXppb25lKToqKiBMYSB2YXJpYWJpbGUgZGkgcmlzcG9zdGEgJFkkIHNlZ3VlIHVuYSBkaXN0cmlidXppb25lIGRpIHByb2JhYmlsaXTDoCBkYWxsYSBmYW1pZ2xpYSBlc3BvbmVuemlhbGUsIGNoZSBpbmNsdWRlIGRpc3RyaWJ1emlvbmkgY29tdW5pIGNvbWUgbm9ybWFsZSwgYmlub21pYWxlIGUgZGkgUG9pc3Nvbi4KCjIuICAqKkNvbXBvbmVudGUgU2lzdGVtYXRpY2EgKFByZWRpdHRvcmUgTGluZWFyZSk6KiogTGEgcmVsYXppb25lIHRyYSBpIHByZWRpdHRvcmkgZSBpbCB2YWxvcmUgYXR0ZXNvIGRlbGxhIHJpc3Bvc3RhIMOoIGVzcHJlc3NhIGF0dHJhdmVyc28gdW4gcHJlZGl0dG9yZSBsaW5lYXJlICgkXGV0YSQpLgogICAgSWwgcHJlZGl0dG9yZSBsaW5lYXJlIMOoIHVuYSBjb21iaW5hemlvbmUgZGVpIHByZWRpdHRvcmksIG9nbnVubyBtb2x0aXBsaWNhdG8gcGVyIHVuIHBhcmFtZXRybywgZSBzaSBjb2xsZWdhIGFsbGEgbWVkaWEgZGVsbGEgcmlzcG9zdGEgYXR0cmF2ZXJzbyB1bmEgZnVuemlvbmUgZGkgY29sbGVnYW1lbnRvLgoKMy4gICoqRnVuemlvbmUgZGkgQ29sbGVnYW1lbnRvOioqIExhIGZ1bnppb25lIGRpIGNvbGxlZ2FtZW50byAoJGcoXG11KSQpIHN0YWJpbGlzY2UgaWwgY29sbGVnYW1lbnRvIHRyYSBpbCBwcmVkaXR0b3JlIGxpbmVhcmUgZSBsYSBtZWRpYSBkZWxsYSByaXNwb3N0YS4KICAgIFRyYXNmb3JtYSBsYSBzY2FsYSBkZWxsYSB2YXJpYWJpbGUgZGkgcmlzcG9zdGEgZSBhc3NpY3VyYSBjaGUgaWwgcHJlZGl0dG9yZSBsaW5lYXJlIGNvcHJhIGwnaW50ZXJhIGxpbmVhIHJlYWxlLgogICAgTGUgZnVuemlvbmkgZGkgY29sbGVnYW1lbnRvIGNvbXVuaSBpbmNsdWRvbm8gbG9naXQsIHByb2JpdCBlIGlkZW50aXTDoC4KCkxhIGZvcm1hIGdlbmVyYWxlIGRpIHVuIEdMTSBwdcOyIGVzc2VyZSByYXBwcmVzZW50YXRhIGNvbWUgc2VndWU6CgokJCBnKFxtdSkgPSBYXGJldGEgJCQKCkRvdmU6CgotICAgJGcoXG11KSQgw6ggbGEgZnVuemlvbmUgZGkgY29sbGVnYW1lbnRvLgotICAgJFxtdSQgw6ggaWwgdmFsb3JlIGF0dGVzbyBkZWxsYSB2YXJpYWJpbGUgZGkgcmlzcG9zdGEuCi0gICAkWCQgw6ggbGEgbWF0cmljZSBkZWkgcHJlZGl0dG9yaS4KLSAgICRcYmV0YSQgw6ggaWwgdmV0dG9yZSBkZWkgY29lZmZpY2llbnRpLgoKKipFc2VtcGk6KioKCjEuICAqKlJlZ3Jlc3Npb25lIExvZ2lzdGljYSBCaW5hcmlhOioqCgogICAgLSAgICoqRGlzdHJpYnV6aW9uZToqKiBCaW5vbWlhbGUKICAgIC0gICAqKkZ1bnppb25lIGRpIENvbGxlZ2FtZW50bzoqKiBMb2dpdCAobG9nLXJhcHBvcnRpIGRpIHByb2JhYmlsaXTDoCkKICAgIC0gICAqKkVxdWF6aW9uZToqKiAkXHRleHR7bG9naXR9KFxtdSkgPSBYXGJldGEkCgogICAgKipEZXNjcml6aW9uZToqKiBMYSBmdW56aW9uZSBkaSBjb2xsZWdhbWVudG8gbG9naXQgdHJhc2Zvcm1hIGxhIHByb2JhYmlsaXTDoCBkaSBzdWNjZXNzbyAoJFxtdSQpIGluIHVuIHByZWRpdHRvcmUgbGluZWFyZS4KICAgIEluIHF1ZXN0byBjYXNvLCBpbCBtb2RlbGxvIGxvZ2lzdGljIGRlc2NyaXZlIGNvbWUgbGEgbG9nLW9kZHMgZGVsbGEgcHJvYmFiaWxpdMOgIGRpIHN1Y2Nlc3NvIHNpYSBsaW5lYXJlIHJpc3BldHRvIGFpIHByZWRpdHRvcmkuCgoyLiAgKipSZWdyZXNzaW9uZSBkaSBQb2lzc29uOioqCgogICAgLSAgICoqRGlzdHJpYnV6aW9uZToqKiBQb2lzc29uCiAgICAtICAgKipGdW56aW9uZSBkaSBDb2xsZWdhbWVudG86KiogTG9nCiAgICAtICAgKipFcXVhemlvbmU6KiogJFxsb2coXG11KSA9IFhcYmV0YSQKCiAgICAqKkRlc2NyaXppb25lOioqIENvbiBsYSBmdW56aW9uZSBkaSBjb2xsZWdhbWVudG8gbG9nYXJpdG1pY28sIGlsIG1vZGVsbG8gZGkgUG9pc3NvbiBwdcOyIGdlc3RpcmUgZGF0aSBkaSBjb250ZWdnaW8sIHBvaWNow6kgY29ubmV0dGUgaWwgbG9nYXJpdG1vIG5hdHVyYWxlIGRlbCB2YWxvcmUgYXR0ZXNvICgkXG11JCkgYSB1biBwcmVkaXR0b3JlIGxpbmVhcmUuCgozLiAgKipSZWdyZXNzaW9uZSBHYW1tYToqKgoKICAgIC0gICAqKkRpc3RyaWJ1emlvbmU6KiogR2FtbWEKICAgIC0gICAqKkZ1bnppb25lIGRpIENvbGxlZ2FtZW50bzoqKiBJbnZlcnNvCiAgICAtICAgKipFcXVhemlvbmU6KiogJFxmcmFjezF9e1xtdX0gPSBYXGJldGEkCgogICAgKipEZXNjcml6aW9uZToqKiBMYSBmdW56aW9uZSBkaSBjb2xsZWdhbWVudG8gaW52ZXJzYSBpbiB1biBtb2RlbGxvIGdhbW1hIMOoIGFwcHJvcHJpYXRhIHF1YW5kbyBzaSBtb2RlbGxhbm8gdmFyaWFiaWxpIGNvbiBkaXN0cmlidXppb25pIGEgY29kYSBwZXNhbnRlLgogICAgQ29sbGVnYSBsJ2ludmVyc28gZGVsIHZhbG9yZSBhdHRlc28gKCRcbXUkKSBhIHVuIHByZWRpdHRvcmUgbGluZWFyZS4KCiMjIyBEZXZpYW56YQoKTGEgZGV2aWFuemEgw6ggdW5hIG1pc3VyYSBkZWxsYSBkaXNjcmVwYW56YSB0cmEgaWwgbW9kZWxsbyBzdGF0aXN0aWNvIGUgaSBkYXRpIG9zc2VydmF0aSBuZWkgR0xNLgpJbiBnZW5lcmFsZSwgbGEgZGV2aWFuemEgw6ggdXRpbGl6emF0YSBwZXIgY29uZnJvbnRhcmUgbW9kZWxsaSBhbHRlcm5hdGl2aSBlIHZhbHV0YXJlIHF1YW50byBiZW5lIHVuIG1vZGVsbG8gc2kgYWRhdHRhIGFpIGRhdGkuCk5lbCBjb250ZXN0byBkZWkgR0xNLCBsYSBkZXZpYW56YSDDqCBwYXJ0aWNvbGFybWVudGUgc2lnbmlmaWNhdGl2YSBwZXJjaMOpIHRpZW5lIGNvbnRvIGRlbGxlIHNwZWNpZmljaGUgZGlzdHJpYnV6aW9uaSBkZWxsZSB2YXJpYWJpbGkgZGkgcmlzcG9zdGEuCgpMYSBkZXZpYW56YSBzaSBjYWxjb2xhIGNvbmZyb250YW5kbyBpbCBtb2RlbGxvIGZpdHRlZCAocHJldmlzdG8pIGNvbiB1biBtb2RlbGxvIG51bGwsIHNwZXNzbyBub3RvIGNvbWUgbW9kZWxsbyBudWxsIGRpIHNhdHVyYXppb25lLgpJbCBtb2RlbGxvIG51bGwgcmFwcHJlc2VudGEgbCdpcG90ZXNpIGNoZSB0dXR0aSBpIHBhcmFtZXRyaSBkZWwgbW9kZWxsbyBzaWFubyB1Z3VhbGkgYSB6ZXJvLCBpbmRpY2FuZG8gbCdhc3NlbnphIGRpIGVmZmV0dGkgcHJlZGl0dG9yaS4KTGEgZGV2aWFuemEgw6ggZGF0YSBkYWxsYSBzZWd1ZW50ZSBmb3JtdWxhOgoKJCQgRCA9IDIgXHRpbWVzIFxsZWZ0KCBcZWxsKFxoYXR7XGJldGF9KSAtIFxlbGwoXGJldGFfMCkgXHJpZ2h0KSAkJAoKRG92ZToKCi0gICAkXGVsbChcaGF0e1xiZXRhfSkkIMOoIGlsIGxvZy1saWtlbGlob29kIGRlbCBtb2RlbGxvIGZpdHRlZC4KLSAgICRcZWxsKFxiZXRhXzApJCDDqCBpbCBsb2ctbGlrZWxpaG9vZCBkZWwgbW9kZWxsbyBudWxsLgotICAgJEQkIMOoIGxhIGRldmlhbnphLgoKUG9pY2jDqSBpIEdMTSB1dGlsaXp6YW5vIGxhIGZhbWlnbGlhIGVzcG9uZW56aWFsZSBkaSBkaXN0cmlidXppb25pLCBsYSBkZXZpYW56YSBhc3N1bWUgdW5hIGZvcm1hIHNwZWNpZmljYSBwZXIgZGl2ZXJzZSBkaXN0cmlidXppb25pLgoKKipGb3JtdWxlIGRlbGxhIFZlcm9zaW1pZ2xpYW56YToqKgoKMS4gICoqTW9kZWxsbyBOb3JtYWxlOioqIExhIHZlcm9zaW1pZ2xpYW56YSBuZWwgY2FzbyBkaSB1bmEgZGlzdHJpYnV6aW9uZSBub3JtYWxlIMOoIGRlZmluaXRhIGRhbGxhIGRlbnNpdMOgIGRpIHByb2JhYmlsaXTDoCBkZWxsYSBkaXN0cmlidXppb25lIG5vcm1hbGUuCiAgICBQZXIgdW5hIHNpbmdvbGEgb3NzZXJ2YXppb25lLCBsYSBmb3JtdWxhIMOoOiAkJCBMKHlfaSB8IFxtdV9pLCBcc2lnbWFeMikgPSBcZnJhY3sxfXtcc3FydHsyXHBpXHNpZ21hXjJ9fSBcZXhwXGxlZnQoLVxmcmFjeyh5X2kgLSBcbXVfaSleMn17MlxzaWdtYV4yfVxyaWdodCkgJCQKCiAgICBEb3ZlOgoKICAgIC0gICAkeV9pJCDDqCBsJ29zc2VydmF6aW9uZSBpLWVzaW1hLgogICAgLSAgICRcbXVfaSQgw6ggaWwgdmFsb3JlIGF0dGVzbyBkZWxsYSB2YXJpYWJpbGUgZGkgcmlzcG9zdGEgaS1lc2ltYS4KICAgIC0gICAkXHNpZ21hXjIkIMOoIGxhIHZhcmlhbnphLgoKMi4gICoqTW9kZWxsbyBkaSBQb2lzc29uOioqIExhIHZlcm9zaW1pZ2xpYW56YSBuZWwgY2FzbyBkaSB1bmEgZGlzdHJpYnV6aW9uZSBkaSBQb2lzc29uIMOoIGRlZmluaXRhIGNvbWUgc2VndWU6ICQkIEwoeV9pIHwgXGxhbWJkYV9pKSA9IFxmcmFje1xsYW1iZGFfaV57eV9pfSBcZXhwKC1cbGFtYmRhX2kpfXt5X2khfSAkJAoKICAgIERvdmU6CgogICAgLSAgICR5X2kkIMOoIGwnb3NzZXJ2YXppb25lIGktZXNpbWEuCiAgICAtICAgJFxsYW1iZGFfaSQgw6ggaWwgdmFsb3JlIGF0dGVzbyBkZWxsYSB2YXJpYWJpbGUgZGkgcmlzcG9zdGEgaS1lc2ltYS4KCkxhIGRldmlhbnphIHB1w7IgZXNzZXJlIGludGVycHJldGF0YSBjb21lIHVuYSBtaXN1cmEgZGVsbGEgZGlzY3JlcGFuemEgdHJhIGlsIG1vZGVsbG8gZml0dGVkIGUgaWwgbW9kZWxsbyBudWxsLgpVbiB2YWxvcmUgZGkgZGV2aWFuemEgcGnDuSBiYXNzbyBpbmRpY2EgdW5hIG1pZ2xpb3JlIGFkYXR0YWJpbGl0w6AgZGVsIG1vZGVsbG8gYWkgZGF0aS4KVHV0dGF2aWEsIHBvaWNow6kgbGEgZGV2aWFuemEgw6ggdW5hIG1pc3VyYSBhc3NvbHV0YSwgw6ggc3Blc3NvIHV0aWxpenphdG8gaWwgY29uY2V0dG8gZGkgZGV2aWFuemEgcmVzaWR1YSwgY2hlIMOoIGxhIGRldmlhbnphIGRpdmlzYSBwZXIgaWwgbnVtZXJvIGRpIGdyYWRpIGRpIGxpYmVydMOgIGRlbCBtb2RlbGxvLgpRdWVzdG8gY29uc2VudGUgdW4gY29uZnJvbnRvIHBpw7kgZXF1byB0cmEgbW9kZWxsaSBjb24gZGlmZmVyZW50aSBjb21wbGVzc2l0w6AuCgpOZWwgY29udGVzdG8gZGVpIEdMTSwgbGEgZGV2aWFuemEgw6ggc3Blc3NvIHNjb21wb3N0YSBpbiB0cmUgY29tcG9uZW50aSBwcmluY2lwYWxpOgoKMS4gICoqTW9kZWxsbyBGaXR0ZWQgRGV2aWFuY2UgKCoqJERfe1x0ZXh0e2ZpdHRlZH19JCk6IE1pc3VyYSBsYSBkaXNjcmVwYW56YSB0cmEgaWwgbW9kZWxsbyBmaXR0ZWQgZSBpIGRhdGkgb3NzZXJ2YXRpLgoKMi4gICoqTnVsbCBEZXZpYW5jZSAoKiokRF97XHRleHR7bnVsbH19JCk6IE1pc3VyYSBsYSBkaXNjcmVwYW56YSB0cmEgaWwgbW9kZWxsbyBudWxsIGUgaSBkYXRpIG9zc2VydmF0aS4KCjMuICAqKlJlc2lkdWFsIERldmlhbmNlICgqKiREX3tcdGV4dHtyZXNpZHVhbH19JCk6IFJhcHByZXNlbnRhIGxhIGRldmlhbnphIHJlc2lkdWEsIGNpb8OoIGxhIGRpc2NyZXBhbnphIG5vbiBzcGllZ2F0YSBkYWwgbW9kZWxsbyBmaXR0ZWQuCgpMJ3V0aWxpenpvIGRpIHF1ZXN0ZSBjb21wb25lbnRpIHBlcm1ldHRlIGRpIGNvbXByZW5kZXJlIGNvbWUgbGEgZGV2aWFuemEgw6ggZGlzdHJpYnVpdGEgdHJhIGlsIG1vZGVsbG8gZml0dGVkLCBpbCBtb2RlbGxvIG51bGwgZSBsYSBkZXZpYW56YSByZXNpZHVhLgoKSWwgdGVzdCBkaSBkZXZpYW56YSDDqCBzcGVzc28gdXRpbGl6emF0byBwZXIgY29uZnJvbnRhcmUgbW9kZWxsaSBhbHRlcm5hdGl2aS4KTGEgZGlmZmVyZW56YSBuZWxsYSBkZXZpYW56YSB0cmEgZHVlIG1vZGVsbGkgc2VndWUgYXBwcm9zc2ltYXRpdmFtZW50ZSB1bmEgZGlzdHJpYnV6aW9uZSBjaGktcXVhZHJvIHNvdHRvIGwnaXBvdGVzaSBudWxsYSBjaGUgaSBkdWUgbW9kZWxsaSBzaWFubyBlcXVpdmFsZW50aS4KUXVlc3RvIHRlc3QgcHXDsiBlc3NlcmUgdXRpbGl6emF0byBwZXIgdmFsdXRhcmUgbCdhZ2dpdW50YSBkaSBwcmVkaXR0b3JpIGFsIG1vZGVsbG8gbyBwZXIgY29uZnJvbnRhcmUgbW9kZWxsaSBjb24gZGlmZmVyZW50aSBzcGVjaWZpY2hlIGRpIGRpc3RyaWJ1emlvbmUgZGVsbGEgcmlzcG9zdGEuCgoqKkVzZW1waW8gZGkgRGV2aWFuemE6KioKCmBgYHtyfQojIENhcmljaGlhbW8gdW4gZGF0YXNldCBkaSBlc2VtcGlvIGluIFIKZGF0YShtdGNhcnMpCgojIENyZWlhbW8gdW4gbW9kZWxsbyBkaSBQb2lzc29uCm1vZGVsX3BvaXNzb24gPC0gZ2xtKHZzIH4gd3QgKyBocCwgZmFtaWx5ID0gcG9pc3NvbiwgZGF0YSA9IG10Y2FycykKCiMgQ2FsY29saWFtbyBsYSBkZXZpYW56YQpkZXZpYW5jZV92YWx1ZSA8LSBkZXZpYW5jZShtb2RlbF9wb2lzc29uKQoKY2F0KCJEZXZpYW56YSBkZWwgTW9kZWxsbyBkaSBQb2lzc29uOiIsIGRldmlhbmNlX3ZhbHVlLCAiXG4iKQoKYGBgCgpJbiBxdWVzdG8gZXNlbXBpbywgY2FsY29saWFtbyBlIHZpc3VhbGl6emlhbW8gbGEgZGV2aWFuemEgcmVzaWR1YSBkaSB1biBtb2RlbGxvIGRpIFBvaXNzb24uCgojIyMgUmVzaWR1aQoKTmVpIEdMTSwgaSByZXNpZHVpIHN2b2xnb25vIHVuIHJ1b2xvIGNydWNpYWxlIG5lbCB2YWx1dGFyZSBsJ2FkYXR0YW1lbnRvIGRlbCBtb2RlbGxvIGFpIGRhdGkgZSBuZWwgdmVyaWZpY2FyZSBsYSB2YWxpZGl0w6AgZGVsbGUgaXBvdGVzaSBkaWV0cm8gaWwgbW9kZWxsby4KQSBkaWZmZXJlbnphIGRlaSBNb2RlbGxpIExpbmVhcmkgKExNKSwgaSByZXNpZHVpIG5laSBHTE0gc29ubyBjYWxjb2xhdGkgY29uc2lkZXJhbmRvIGxhIGRpc3RyaWJ1emlvbmUgZGVsbGEgcmlzcG9zdGEgc3BlY2lmaWNhIGRlbCBtb2RlbGxvLgoKMS4gICoqTWlzdXJhcmUgbGEgQm9udMOgIGRpIEFkYXR0YW1lbnRvOioqCiAgICAtICAgSSByZXNpZHVpIG5laSBHTE0gc29ubyB1dGlsaXp6YXRpIHBlciB2YWx1dGFyZSBsYSBib250w6AgZGkgYWRhdHRhbWVudG8gZGVsIG1vZGVsbG8uIFNlIGlsIG1vZGVsbG8gc2kgYWRhdHRhIGJlbmUgYWkgZGF0aSwgY2kgc2kgYXNwZXR0YSBjaGUgaSByZXNpZHVpIGFiYmlhbm8gdW5hIGRpc3RyaWJ1emlvbmUgY2hlIHJpZmxldHRlIGxhIGRpc3RyaWJ1emlvbmUgZGVsbGEgcmlzcG9zdGEgc3BlY2lmaWNhdGEgbmVsIEdMTS4KMi4gICoqSW5kaWNhemlvbmkgc3VsbGEgU3RydXR0dXJhIGRlaSBEYXRpOioqCiAgICAtICAgTmVpIEdMTSwgbGEgc2NlbHRhIGRlbGxhIGRpc3RyaWJ1emlvbmUgZGVsbGEgcmlzcG9zdGEgZSBkZWxsYSBmdW56aW9uZSBkaSBsZWdhbWUgcHXDsiB2YXJpYXJlIGluIGJhc2UgYWxsYSBuYXR1cmEgZGVpIGRhdGkuIEkgcmVzaWR1aSBmb3JuaXNjb25vIGluZGljYXppb25pIHN1bGxhIHN0cnV0dHVyYSBkZWkgZGF0aSBlIHN1bGxhIHZhbGlkaXTDoCBkZWxsZSBpcG90ZXNpIGRlbCBtb2RlbGxvLgozLiAgKipEaWFnbm9zdGljYXJlIERldmlhbnphOioqCiAgICAtICAgTGEgZGV2aWFuemEsIHVuYSBtaXN1cmEgZGVsbGEgZGlmZmVyZW56YSB0cmEgaWwgbW9kZWxsbyBjb21wbGV0byBlIHVubyBwacO5IHNlbXBsaWNlLCBwdcOyIGVzc2VyZSBkaWFnbm9zdGljYXRhIGF0dHJhdmVyc28gaSByZXNpZHVpLiBSZXNpZHVpIGRldmlhbnRpIGUgc3RhbmRhcmRpemVkIGRldmlhbmNlIHJlc2lkdWFscyBzb25vIHNwZXNzbyB1dGlsaXp6YXRpIHBlciBpbmRpdmlkdWFyZSBtb2RlbGxpIG5vbiBhZGF0dGkgYWkgZGF0aS4KCkxlIHByaW5jaXBhbGkgZGlmZmVyZW56ZSB0cmEgaSByZXNpZHVpIG5laSBHTE0gZSBuZWkgTE0gcmlndWFyZGFubyBsYSBkaXN0cmlidXppb25lIGRlbGxhIHJpc3Bvc3RhIGUgbGEgZnVuemlvbmUgZGkgbGVnYW1lLgoKMS4gICoqRGlzdHJpYnV6aW9uZSBkZWxsYSBSaXNwb3N0YToqKgogICAgLSAgIE5laSBHTE0sIGkgcmVzaWR1aSBzb25vIGNhbGNvbGF0aSB0ZW5lbmRvIGNvbnRvIGRlbGxhIGRpc3RyaWJ1emlvbmUgZGVsbGEgcmlzcG9zdGEgc3BlY2lmaWNhdGEgbmVsIG1vZGVsbG8uIEFkIGVzZW1waW8sIG5laSBtb2RlbGxpIGRpIFBvaXNzb24sIGkgcmVzaWR1aSBkZXZvbm8gYWRhdHRhcnNpIGFsbGEgZGlzdHJpYnV6aW9uZSBkaSBQb2lzc29uLgogICAgLSAgIE5laSBMTSwgaSByZXNpZHVpIHNvbm8gYmFzYXRpIHN1bGwnYXNzdW56aW9uZSBjaGUgbGEgcmlzcG9zdGEgc2lhIGRpc3RyaWJ1aXRhIG5vcm1hbG1lbnRlLgoyLiAgKipGdW56aW9uZSBkaSBMZWdhbWU6KioKICAgIC0gICBMYSBmdW56aW9uZSBkaSBsZWdhbWUgbmVpIEdMTSBkZXRlcm1pbmEgY29tZSBpbCB2YWxvcmUgYXR0ZXNvIGRlbGxhIHJpc3Bvc3RhIMOoIGNvbGxlZ2F0byBhbGxhIGNvbWJpbmF6aW9uZSBsaW5lYXJlIGRlaSBwcmVkaXR0b3JpLiBMYSBzY2VsdGEgZGVsbGEgZnVuemlvbmUgZGkgbGVnYW1lIGluZmx1ZW56YSBpIHJlc2lkdWkuCiAgICAtICAgTmVpIExNLCBsYSBmdW56aW9uZSBkaSBsZWdhbWUgw6ggaWRlbnRpdMOgLCBlIGkgcmVzaWR1aSByaWZsZXR0b25vIHNlbXBsaWNlbWVudGUgbGEgZGlmZmVyZW56YSB0cmEgaSB2YWxvcmkgb3NzZXJ2YXRpIGUgcXVlbGxpIHByZXZpc3RpLgoKKipFc2VtcGlvIGRpIENhbGNvbG8gZGVpIFJlc2lkdWkgaW4gdW4gTW9kZWxsbyBHTE06KioKCmBgYHtyfQpzdXBwcmVzc1dhcm5pbmdzKHsKIyBDYXJpY2hpYW1vIHVuIGRhdGFzZXQgZGkgZXNlbXBpbyBpbiBSIGNvbiB1bmEgZGlzdHJpYnV6aW9uZSBkaSBQb2lzc29uCmRhdGEoZmFpdGhmdWwsIHBhY2thZ2UgPSAiZGF0YXNldHMiKQoKIyBDcmVpYW1vIHVuIG1vZGVsbG8gZGkgUG9pc3Nvbgptb2RlbGxvX3BvaXNzb24gPC0gZ2xtKGVydXB0aW9ucyB+IHdhaXRpbmcsIGZhbWlseSA9IHBvaXNzb24sIGRhdGEgPSBmYWl0aGZ1bCkKCiMgQ2FsY29saWFtbyBpIHJlc2lkdWkgZGV2aWFudGkKcmVzaWR1aV9kZXZpYW50aSA8LSByZXNpZHVhbHMobW9kZWxsb19wb2lzc29uLCB0eXBlID0gImRldmlhbmNlIikKCiMgVmlzdWFsaXp6aWFtbyBpIHByaW1pIDEwIHJlc2lkdWkgZGV2aWFudGkKaGVhZChyZXNpZHVpX2RldmlhbnRpKQp9KQpgYGAKCkkgcmVzaWR1aSBkZXZpYW50aSByaWZsZXR0b25vIGxlIGRpZmZlcmVuemUgdHJhIGkgdmFsb3JpIG9zc2VydmF0aSBlIHF1ZWxsaSBwcmV2aXN0aSBpbiB0ZXJtaW5pIGRlbGxhIGRldmlhbnphIGRlbCBtb2RlbGxvLgpVbiByZXNpZHVvIGRldmlhbnRlIGVsZXZhdG8gaW5kaWNhIGNoZSBsJ29zc2VydmF6aW9uZSBjb250cmlidWlzY2UgaW4gbW9kbyBzaWduaWZpY2F0aXZvIGFsbGEgZGV2aWFuemEgY29tcGxlc3NpdmEgZGVsIG1vZGVsbG8sIGluZGljYW5kbyB1bidldmVudHVhbGUgaW5mbHVlbnphIG8gZGV2aWF6aW9uZSBkYWwgbW9kZWxsby4KCi0gICBSZXNpZHVpIHBvc2l0aXZpIGluZGljYW5vIGNoZSBsJ29zc2VydmF6aW9uZSBoYSBjb250cmlidWl0byBwacO5IGRlbCBwcmV2aXN0byBhbGxhIGRldmlhbnphLgotICAgUmVzaWR1aSBuZWdhdGl2aSBpbmRpY2FubyBjaGUgbCdvc3NlcnZhemlvbmUgaGEgY29udHJpYnVpdG8gbWVubyBkZWwgcHJldmlzdG8gYWxsYSBkZXZpYW56YS4KLSAgIFJlc2lkdWkgcGFyaSBhIHplcm8gaW5kaWNhbm8gdW5hIHBlcmZldHRhIGFkYXR0YWJpbGl0w6AgZGVsbCdvc3NlcnZhemlvbmUgYWwgbW9kZWxsby4KCioqRXNlbXBpbzoqKgoKUGVyIHF1ZXN0byBlc2VtcGlvLCB1c2VyZW1vIGlsIGRhdGFzZXQgZGkgZXNlbXBpbyAibXRjYXJzIiBkaSBSIHBlciBjcmVhcmUgdW4gbW9kZWxsbyBkaSBQb2lzc29uIHV0aWxpenphbmRvIHVuIG1vZGVsbG8gZ2VuZXJhbGl6emF0byBsaW5lYXJlIChHTE0pLgpMbyBzY29wbyBkZWwgbW9kZWxsbyBzYXLDoCBwcmV2ZWRlcmUgaWwgbnVtZXJvIGRpIGNpbGluZHJpICgiY3lsIikgaW4gYmFzZSBhbGxlIGFsdHJlIHZhcmlhYmlsaSBwcmVzZW50aSBuZWwgZGF0YXNldC4KCmBgYHtyfQojIENhcmljYW1lbnRvIGRlbCBkYXRhc2V0ICJtdGNhcnMiCmRhdGEobXRjYXJzKQoKIyBFc3Bsb3JpYW1vIGxlIHByaW1lIHJpZ2hlIGRlbCBkYXRhc2V0CmhlYWQobXRjYXJzKQoKIyBDcmVpYW1vIHVuIG1vZGVsbG8gZGkgUG9pc3NvbiBwZXIgcHJldmVkZXJlIGlsIG51bWVybyBkaSBjaWxpbmRyaSBpbiBiYXNlIGFsbGUgYWx0cmUgdmFyaWFiaWxpCm1vZGVsbG9fZ2xtIDwtIGdsbShjeWwgfiBtcGcgKyBkaXNwICsgaHAgKyBkcmF0ICsgd3QgKyBxc2VjICsgdnMgKyBhbSArIGdlYXIgKyBjYXJiLCAKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBtdGNhcnMsIGZhbWlseSA9IHBvaXNzb24pCgojIFZpc3VhbGl6emlhbW8gaWwgc3VtbWFyeSBkZWwgbW9kZWxsbwpzdW1tYXJ5KG1vZGVsbG9fZ2xtKQoKIyBBbmFsaXp6aWFtbyBsZSB2YXJpYWJpbGkgaW5kaXBlbmRlbnRpCnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QobW9kZWxsb19nbG0pCgojIEVzZWd1aWFtbyBsJ2FuYWxpc2kgZGVsbGEgdmFyaWFuemEgKEFOT1ZBKQphbm92YV9yZXN1bHQgPC0gYW5vdmEobW9kZWxsb19nbG0sIHRlc3QgPSAiQ2hpIikKCiMgVmlzdWFsaXp6aWFtbyBsYSB0YWJlbGxhIEFOT1ZBCnByaW50KGFub3ZhX3Jlc3VsdCkKCiMgQ2FsY29saWFtbyBsJ1Itc3F1YXJlZCBkZWwgbW9kZWxsbwpyX3NxdWFyZWQgPC0gMSAtIChtb2RlbGxvX2dsbSRkZXZpYW5jZSAvIG1vZGVsbG9fZ2xtJG51bGwuZGV2aWFuY2UpCmNhdCgiUi1zcXVhcmVkOiIsIHJfc3F1YXJlZCwgIlxuIikKCiMgRWZmZXR0dWlhbW8gcHJldmlzaW9uaSBzdSBudW92aSBkYXRpIChwZXIgZXNlbXBpbywgbGUgcHJpbWUgNSBvc3NlcnZhemlvbmkgZGVsIGRhdGFzZXQpCm51b3ZpX2RhdGkgPC0gbXRjYXJzWzE6NSwgXQpwcmV2aXNpb25pIDwtIHByZWRpY3QobW9kZWxsb19nbG0sIG5ld2RhdGEgPSBudW92aV9kYXRpLCB0eXBlID0gInJlc3BvbnNlIikKY2F0KCJQcmV2aXNpb25pIHBlciBsZSBwcmltZSA1IG9zc2VydmF6aW9uaTpcbiIsIHByZXZpc2lvbmksICJcbiIpCmBgYAoKSW4gcXVlc3RvIGVzZW1waW8sIGFiYmlhbW8gY3JlYXRvIHVuIG1vZGVsbG8gZGkgUG9pc3NvbiB1dGlsaXp6YW5kbyBpbCBudW1lcm8gZGkgY2lsaW5kcmkgY29tZSB2YXJpYWJpbGUgZGlwZW5kZW50ZSBlIGxlIGFsdHJlIHZhcmlhYmlsaSBkZWwgZGF0YXNldCAibXRjYXJzIiBjb21lIHZhcmlhYmlsaSBpbmRpcGVuZGVudGkuClN1Y2Nlc3NpdmFtZW50ZSwgYWJiaWFtbyBlc2VndWl0byB1bidhbmFsaXNpIGNvbXBsZXRhIGRlbCBtb2RlbGxvLCBjb21wcmVzaSBpbCBzdW1tYXJ5LCBsYSB2aXN1YWxpenphemlvbmUgZGVsbGUgdmFyaWFiaWxpIGluZGlwZW5kZW50aSwgbCdhbmFsaXNpIGRlbGxhIHZhcmlhbnphIChBTk9WQSksIGlsIGNhbGNvbG8gZGVsbCdSLXNxdWFyZWQgZSBsYSBwcmV2aXNpb25lIHN1IG51b3ZpIGRhdGkuCgpbW1Rvcm5hIGFsbCcgW0luZGljZV1dXQo=